首页 > 解决方案 > 如何将 SwiftUI 元素绑定到字典中的值?

问题描述

我有一本字典,其中包含我想要“过滤”的各种值。所以我正在做这样的事情

struct ExampleView : View {

    @EnvironmentObject var externalData : ExternalData

    var body: some View {
        VStack {
            ForEach(externalData.filters) { (v : (String, Bool)) in
                Toggle(isOn: $externalData.filters[v.0], label: {
                    Text("\(v.0)")
                })
            }
        }
    }
}

final class ExternalData : BindableObject {

    let didChange = PassthroughSubject<ExternalData, Never>()

    init() {
        filters["Juniper"] = true
        filters["Beans"] = false
    }

    var filters : Dictionary<String, Bool> = [:] {
        didSet {
            didChange.send(self)
        }
    }
}

这个问题似乎相关,但放置动态似乎没有帮助,我无法弄清楚在这种情况下如何做 NSObject 继承的事情。现在,这段代码给了我这个错误:

Cannot subscript a value of type 'Binding<[String : Bool]>' with an argument of type 'String'

但是尝试移动 $ 或以各种方式使用 paren 似乎无济于事。如何将切换绑定到字典中的值?我可以为每个值进行手动切换,但这会使代码变得脆弱,因为(除其他原因外)潜在的过滤器值基于可能在某些时候具有新值的数据集。

我知道在迭代它们之前我真的应该(以某种方式)对键进行排序,以便排序是一致的,但这会使这个例子变得混乱,所以我把那个代码省略了。

标签: swiftui

解决方案


我设法通过为每个过滤器使用自定义绑定来完成工作。

final class ExternalData: BindableObject {
    let didChange = PassthroughSubject<Void, Never>()

    var filters: Dictionary<String, Bool> = [:] {
        didSet {
            didChange.send(())
        }
    }

    init() {
        filters["Juniper"] = true
        filters["Beans"] = false
    }

    var keys: [String] {
        return Array(filters.keys)
    }

    func binding(for key: String) -> Binding<Bool> {
        return Binding(getValue: {
            return self.filters[key] ?? false
        }, setValue: {
            self.filters[key] = $0
        })
    }
}

keys属性列出了filters键,String以便可以显示(使用ForEach(externalData.keys)

binding(for:)方法为给定的键创建自定义Binding。这个绑定被赋予Toggle读/写包装字典中的当前值。

视图代码:

struct ExampleView : View {

    @EnvironmentObject var externalData : ExternalData

    var body: some View {
        VStack {
            ForEach(externalData.keys) { key in
                Toggle(isOn: self.externalData.binding(for: key)) {
                    Text(key)
                }
            }
        }
    }
}

推荐阅读