Home > OS >  How to create a dictionary of which the value is @State?
How to create a dictionary of which the value is @State?

Time:10-24

I've tried the following (simplified extraction):

struct MyView : View {
    var names: [String]

    @State private var flags = [String : Bool]()

    var body: some View {
        ForEach(names, id: \.self) { name in
            Toggle(isOn: $flags[name]) { <== ERRORS
                ...
            }
        }
        .onAppear {
            for name in names {
                flags[name] = false
            }
        }
    }
}

This results in three errors:

  • Cannot convert value of type 'Slice<Binding<[String : Bool]>>' to expected argument type 'Binding<Bool>'
  • Cannot convert value of type 'String' to expected argument type 'Range<Binding<[String : Bool]>.Index>'
  • Referencing subscript 'subscript(_:)' on 'Binding' requires that '[String : Bool]' conform to 'MutableCollection'

Probably a silly question, but why doesn't $flags[name], which is a dictionary, simply result in one value: a Binding<Bool>?

How can this be resolved?

CodePudding user response:

Quick work around to get this working: manually create the binding:


        
Toggle(isOn: .init(
    get: { flags[name] ?? false },
    set: { flags[name] = $0 }
)) { 
    // ...
}

I'm looking into it why $flags[name]doesn't result in a Binding. It might be related to dictionary[key] returning an optional<value> instead of the value directly.

Another hypothesis is, in Swift, that brackets are mostly syntax sugar to call the subscript function. A function cannot be bound to, as it's only read only and bindings need write access to modify the value. This also explains why you can't bind to an array element, but I'm not 100% sure on either answer and would be happy to edit this in favor of the community

  • Related