首页 > 解决方案 > 如何在 SwiftUI 中设置自定义环境键?

问题描述

创建自定义环境键有效,但如果我希望在视图中设置值,XCODE 不允许这样做。但是可以设置预定义的环境值。我究竟做错了什么?

struct ResetDefault: EnvironmentKey {
    static var defaultValue: Bool = false
}

extension EnvironmentValues {
    var resetDefault: Bool {
        get { self[ResetDefault.self] }
        set { self[ResetDefault.self] = newValue }
    }
}

struct ResetView: View {
    @Environment(\.resetDefault) var reset
    var body: some View {
        Text("Reset").onAppear() {
            reset = true.        // Cannot assign to property: 'reset' is a get-only property
        }
    }
}

标签: swiftui

解决方案


Environment用于按方向传递值,因此parent > child设置值以供使用。如果要更改环境值的内部,则需要以某种方式包装它,可能的变体是绑定或引用类型持有者。

这是一个基于绑定的使用示例(类似于 .editMode 和 .presentationMode 的工作方式)

struct TestResetEnv: View {
    @State private var isActive = false
    @State private var reset = false
    var body: some View {
        VStack {
            Text("Current: \(reset ? "true" : "false")")
            Button("Go") { self.isActive.toggle() }
            if isActive {
                ResetView()
            }
        }.environment(\.resetDefault, $reset) // set for children as env!!
    }
}

struct ResetDefault: EnvironmentKey {
    static var defaultValue: Binding<Bool> = .constant(false)
}

extension EnvironmentValues {
    var resetDefault: Binding<Bool> {
        get { self[ResetDefault.self] }
        set { self[ResetDefault.self] = newValue }
    }
}

struct ResetView: View {
    @Environment(\.resetDefault) var reset
    var body: some View {
        Text("Reset").onAppear() {
            self.reset.wrappedValue.toggle() // << change wrapped !!
        }
    }
}

推荐阅读