SwiftUI学习@Environment

一、@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协议对象
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容