skip to Main Content

This code does not work, meaning onChange is never called and the variable is not changed when a dropdown option is selected.

struct ExamplePicker: View {
    
    @State var val: Int32 = 2
    
    var body: some View {
        HStack {
            
            Menu {
                
                Picker(selection: $val, label: EmptyView()) {
                    
                    Text("Val1").tag(1)
                    Text("Val2").tag(2)
                    Text("Val3").tag(3)
                }
                
                
            } label: {
                HStack {
                    Text("Value: ")
                    Spacer()
                    
                    Text(String(format: "%d", val))
                    
                    Spacer()
                }
                
            }
            .onChange(of: val) { newSelection in
               print(">>> HERE")
           }
            
            
        }
        
    }
}

but if you change val to type Int it works perfectly fine.
This looks like a bug to me

EDIT:
Solved – the problem is that in .tag() you need the EXACT same type.
so .tag(1) would be Int not Int32. and thus .tag(Int32(1)) is needed

2

Answers


  1. It works fine when the tag values of the Picker items have the same type as the state variable. Like this:

    Picker(selection: $val, label: EmptyView()) {
        Text("Val1").tag(Int32(1))
        Text("Val2").tag(Int32(2))
        Text("Val3").tag(Int32(3))
    }
    
    Login or Signup to reply.
  2. When you do .tag(1), the type of 1 is Int. tag does not know anything about what type of Binding you have passed to selection: – any Hashable thing can go in there:

    func tag<V>(_ tag: V) -> some View where V : Hashable
    

    By type inference, 1 in tag(1) is inferred to be Int, because I repeat, tag doesn’t know anything about selection:.

    So the type of the selection: binding is different from the type of the tag. This means that when you select something in the picker, SwiftUI doesn’t know what it should change the selection value to. It also doesn’t know which option is currently selected, for the same reason.

    To make a Int32 selection work, explicitly say that 1, 2, 3 etc are Int32s:

    Text("Val1").tag(Int32(1))
    Text("Val2").tag(Int32(2))
    Text("Val3").tag(Int32(3))
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search