• SwiftUI 中 @Environment 的用法


    Environment 中的 Core Data Context

    在使用 Core Data 时会看到这样的代码:

    @Environment(.managedObjectContext) var managedObjectContext
    

    在 Previews 视图代码中还要这样写:

    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    return ContentView().environment(.managedObjectContext, context)
    

    追溯源头,会发现在 SceneDelegate.swift 中有最早的使用:

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
    
        // Get the managed object context from the shared persistent container.
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    
        // Create the SwiftUI view and set the context as the value for the managedObjectContext environment keyPath.
        // Add `@Environment(.managedObjectContext)` in the views that will need the context.
        let contentView = ContentView().environment(.managedObjectContext, context)
    
        // Use a UIHostingController as window root view controlle
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: contentView)
            self.window = window
            window.makeKeyAndVisible()
        }
    }
    

    由代码可知,context 在一开始就被创建,然后以 .environment(.managedObjectContext, context) 的方式存放在 Environment 之中,供其他 View 共享。

    那么 @Environment 究竟是什么呢?

    顾名思义,@Environment 就是 View 所在环境的各种环境变量信息的集合。你可以通过键路径 (key path) 对其读写。

    除了 managedObjectContext 用于 Core Data 的 context 外,很多 UI 的设计都可以利用到 Environment 的各种键值。

    用例:Environment.colorScheme

    根据 Light 和 Dark 两种系统颜色模式来调整 app 界面的配色是很常见的需求。方法很简单,通过 Environment.colorScheme 获取当前系统环境的颜色方案就行了:

    struct ContentView: View {
    	// colorScheme values: .light, .dark
        @Enviroment(.colorScheme) var colorScheme
        
        var body: some View {
            Text("Hello, World")
                .foregroundColor(colorScheme = .light ? .yellow : .blue)
        }
    }
    

    查阅 EnvironmentValues 文档可以获得更多键值的用法。

    自定义 Environment 的 Key

    Environment 如此方便好用,不能自定义键值为我所用岂不可惜?

    用稍微复杂点的对象来举例。首先定义一个结构体:

    struct Setting {
        var username: String = ""
        var isSoundOn: Bool = false
        init(name: String) {
        	self.username = name
        }
    }
    

    接下来我们要把它变成 Environment 的一个键 (EnvironmentKey):

    struct SettingKey: EnvironmentKey {
        static var defaultValue: Setting {
            return Setting(name: "User")
        }
    }
    

    这样用到这个 key 就可以获取它的默认值。

    然后我们要扩写 EnvironmentValues,把 Setting 加进去:

    extension EnvironmentValues {
        var customSetting: Setting {
            get { return self[SettingKey.self] }
            set { self[SettingKey] = newValue }
        }
    }
    

    就这样,customSetting 变成了 Environment 的 key,我们可以通过声明 @Environment(.customSetting) var customSetting: Setting 来获取它的值,通过在 View 中 .environment(.customSetting, Setting(name: "...")) 来修改它。

    参考

    本文参考了以下文章和视频:

  • 相关阅读:
    How to function call using 'this' inside forEach loop
    jquery.validate.unobtrusive not working with dynamic injected elements
    Difference between jQuery.extend and jQuery.fn.extend?
    Methods, Computed, and Watchers in Vue.js
    Caution using watchers for objects in Vue
    How to Watch Deep Data Structures in Vue (Arrays and Objects)
    Page: DOMContentLoaded, load, beforeunload, unload
    linux bridge
    linux bridge
    EVE-NG网卡桥接
  • 原文地址:https://www.cnblogs.com/seesawgame/p/14325473.html
Copyright © 2020-2023  润新知