一、@Environment
@frozen @propertyWrapper
struct Environment<Value>
一种从视图环境中读取值的属性包装器。在属性声明时通过环境值键路径(EnvironmentValues key path)指定需要读取的值。
例如,可以通过颜色方案的键路径创建读取当前视图颜色方案的属性。
struct ContentView: View {
@Environment(\.colorScheme) var colorScheme
var body: some View {
if colorScheme == .dark {
Text("深色模式内容")
.foregroundColor(.white)
} else {
Text("浅色模式内容")
.foregroundColor(.black)
}
}
}
在这个示例中,当系统主题切换时,所有使用该颜色方案的视图都会自动适配新主题,无需手动监听变化。
再例如获取当前环境的 DismissAction 实例关闭模态视图(Sheet/Popover)或者弹出导航栈中的视图
struct ModalView: View {
@Environment(\.dismiss) private var dismiss
var body: some View {
Button("Close") {
dismiss() // 调用环境提供的 dismiss 方法
}
}
}
上面都是内置的SwiftUI 环境变量,可以通过@Environment像上面 直接获取。
二、自定义环境变量
// 定义环境键
struct DismissActionKey: EnvironmentKey {
static let defaultValue: (() -> Void)? = nil
}
extension EnvironmentValues {
var dismissAction: (() -> Void)? {
get { self[DismissActionKey.self] }
set { self[DismissActionKey.self] = newValue }
}
}
- 1、所有自定义环境键必须继承自 EnvironmentKey,这是 SwiftUI 环境变量系统的识别标志;定义环境变量存储的类型可以是任意类型比如String、Int、对象等,这里存储的是一个闭包
- 2、通过 self[DismissActionKey.self] 从环境容器中读取值,通过 self[DismissActionKey.self] = newValue 向环境容器写入值; 将自定义键 .dismissAction 绑定到 () -> Void? 类型的闭包。
之前系统预设的环境变量,由 SwiftUI 框架统一维护,作用域覆盖整个视图树。而我们自定义的环境需要显式注入到关联的视图中。
// 手动注入自定义环境变量
LoginView().environment(\.dismissAction, {
print("dismiss了")
})
三、@Environment和 @EnvironmentObject
- 1.@Environment可以 注入简单类型的环境值(如 String、Bool、Color、自定义闭包等,也可以注入遵循 ObservableObject 的对象,但不会自动监听对象属性变化
- 2、注入复杂对象(必须遵循 ObservableObject 协议),并自动监听对象属性变化
- 3、你也可以使用@Environment监听Observable协议对象