在使用 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)