zoukankan      html  css  js  c++  java
  • 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: "...")) 来修改它。

    参考

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

  • 相关阅读:
    Linux
    python中元类
    POJ 1182 食物链
    POJ 1733 Parity game
    top 介绍
    周记 2014.8.31
    windows10配置python
    oracle执行update时卡死问题的解决办法
    An Easy Introduction to CUDA C and C++
    super()
  • 原文地址:https://www.cnblogs.com/seesawgame/p/14325473.html
Copyright © 2011-2022 走看看