如何将 SwiftUI 元素绑定到字典中的值? [英] How do I bind a SwiftUI element to a value in a Dictionary?

查看:25
本文介绍了如何将 SwiftUI 元素绑定到字典中的值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a dictionary that contains various values I want to "filter" by. So I'm doing something like this

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)
        }
    }
}

这个问题似乎相关,但把dynamic 似乎没有帮助,我无法弄清楚在这种情况下如何进行 NSObject 继承.现在,这个代码给了我这个错误:

This question seems related, but putting dynamic didn't seem to help and I wasn't able to figure out how to do that NSObject inheritance thing in this case. Right now, this code as is gives me this error:

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

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

But trying to move the $ around or use paren in various ways doesn't seem to help. How can I bind the toggles to the values in my dictionary? I could just make manual toggles for each value, but that makes fragile code since (among other reasons) the potential filter values are based on a dataset that might have new values at some point.

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

I'm aware that I should really sort the keys (in some way) before iterating over them so the ordering is consistent, but that clutters this example so I left that code out.

推荐答案

我设法通过为每个过滤器使用自定义绑定来实现工作.

I managed to make is work by using a custom binding for each filter.

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))

The keys property list the filters keys as String so that it can be displayed (using ForEach(externalData.keys))

binding(for:) 方法,为给定的键创建一个自定义的Binding.此绑定被赋予 Toggle 以读取/写入包装字典中的当前值.

The binding(for:) method, create a custom Binding for the given key. This binding is given to the Toggle to read/write the current value in the wrapped dictionary.

查看代码:

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)
                }
            }
        }
    }
}

这篇关于如何将 SwiftUI 元素绑定到字典中的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆