在使用 Core Data 时会看到这样的代码:html
@Environment(\.managedObjectContext) var managedObjectContext
在 Previews 视图代码中还要这样写:swift
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext return ContentView().environment(\.managedObjectContext, context)
追溯源头,会发如今 SceneDelegate.swift
中有最先的使用:session
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 共享。app
那么 @Environment 到底是什么呢?ide
顾名思义,@Environment 就是 View 所在环境的各类环境变量信息的集合。你能够经过键路径 (key path) 对其读写。ui
除了 managedObjectContext 用于 Core Data 的 context 外,不少 UI 的设计均可以利用到 Environment 的各类键值。this
根据 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 文档能够得到更多键值的用法。code
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: "..."))
来修改它。
本文参考了如下文章和视频:
When Should I Use @State, @Binding, @ObservedObject, @EnvironmentObject, or @Environment?
Environment Variables in SwiftUI
@Environment in SwiftUI - What is it? How to use it? (2020)