0

In the following code, I have a Picker bound to array, which is an @AppStorage variable.

The issue is that the picker never shows "value2" as the selected item, even though it's being set in the .onAppear method. Why isn't this working?

Debugging shows that the .onAppear is working, and that array["item1"] has a value of Optional("value2") despite the Picker not showing these changes. I assume it has to do with the optional value, but I'm not sure how.

struct ContentView: View {
    
    @AppStorage("array") var array: [String : String] = ["item1":"value1"]
    
    var body: some View {
        
        Picker("", selection: $array["item1"]) {
            Text("value1").tag("value1")
            Text("value2").tag("value2")
            Text("value3").tag("value3")
        }
        .onAppear {
            array["item1"] = "value2"
        }
    }
}

Note I'm using this extension to save dictionaries in @AppStorage in XCode 15 beta 5

Stoic
  • 945
  • 12
  • 22

1 Answers1

1

The hint is in the debugging you mentioned. The type is an Optional and your Picker tag must match the type exactly. String != Optional(String)

Picker("", selection: $array["item1"]) {
    Text("value1").tag(Optional("value1"))
    Text("value2").tag(Optional("value2"))
    Text("value3").tag(Optional("value3"))
}
jnpdx
  • 45,847
  • 6
  • 64
  • 94
  • Got it, thanks. Why doesn't `$array["item1"]!` work? It throws an error, but why can't we unwrap the `selection` instead of casting the `.tag` as optional? – Stoic Aug 01 '23 at 23:39
  • I think if it were just `array["item1"]` you might be okay with that, but the `$` adds a wrinkle -- it's probably the `Binding` that creates that is getting in the way. You could create a custom `Binding` that returns a non-Optional. – jnpdx Aug 01 '23 at 23:41