10

After updating to iOS 15 and Xcode 13, my picker in my app is no longer showing a custom label. Running the app on an iOS 14 device, the pickers render fine.

This is the code snippet that is currently implemented and the screenshot is what it currently looks like in the simulator on iOS 15.

    @State var selectedNumber: Int = 0
    
    var body: some View {
        Picker(selection: $selectedNumber, label: customLabel) {
            ForEach(0..<10) {
                Text("\($0)")
            }
        }
    }
    
    var customLabel: some View {
        HStack {
            Image(systemName: "paperplane")
            Text(String(selectedNumber))
            Spacer()
            Text("⌵")
                .offset(y: -4)
        }
        .foregroundColor(.white)
        .font(.title)
        .padding()
        .frame(height: 32)
        .background(Color.blue)
        .cornerRadius(16)
    }

screenshot

Talon
  • 811
  • 7
  • 22
  • 1
    Use a Menu with a Picker inside it, like my answer here: https://stackoverflow.com/a/68897763/1601849 – Adam Sep 29 '21 at 18:43

3 Answers3

18

The answer @Adam provided worked. Below is what I did to fix it in case someone else stumbles on problem.

@State var selectedNumber: Int = 0

var body: some View {
    Menu {
        Picker(selection: $selectedNumber, label: EmptyView()) {
            ForEach(0..<10) {
                Text("\($0)")
            }
        }
    } label: {
        customLabel
    }
}

var customLabel: some View {
    HStack {
        Image(systemName: "paperplane")
        Text(String(selectedNumber))
        Spacer()
        Text("⌵")
            .offset(y: -4)
    }
    .foregroundColor(.white)
    .font(.title)
    .padding()
    .frame(height: 32)
    .background(Color.blue)
    .cornerRadius(16)
}
pkamb
  • 33,281
  • 23
  • 160
  • 191
Talon
  • 811
  • 7
  • 22
  • 3
    This method seems to not auto center the list on the selected value. It's a problem with long lists which extend out of the screen. – Quentin Hayot Nov 25 '21 at 00:01
  • in watchOS with Xcode 14.1, this solution doesn't work, the label is only shown when the picker is active. – lewis Oct 13 '22 at 10:14
3

Your can Use Menu Options as label

Menu("Drop Your Label Here") {
        Picker("Please choose a color", selection: $selectedColor)
        {
            ForEach(colors, id: \.self) {
                Text($0)
            }
        }
        
    }
    //.foregroundColor(Color.init("Red"))
    .foregroundColor(Color.red)
}.frame(width: 300, height: 60)
pkamb
  • 33,281
  • 23
  • 160
  • 191
Amit Raj
  • 31
  • 2
0

I've been struggling with this issue and it's still exists (xcode 14 beta iOS 16). I came up with this solution I hope it helps someone until Apple solve this

The label will not show if the selected item is not exist in the array items. So I'm adding the label in the array and the same label have to be the vale of the selected item. this will cause the label showing all the time so when the user click to popup the list delete the label if you want.

@State private var items = ["please select an option","Option1","Option2","Option3","Option4","Option5"]
@State private var selectedItem = "please select an option"   

var body: some View {

Picker(selection: $selectedItem, label: Text(selectedItem)) {
    ForEach(items, id: \.self) {
        Text($0)
    }
    }.onTapGesture(){
        if items.contains("please select an option") {
            items.remove(at: 0)
        }   
    }   

}

Same code here in case you have an array of your own object instead of Strings Make sure to use Int { hashValue } as id of your object

struct myStruct: Hashable, Identifiable {
    var id: Int { hashValue } //UUID is not going to work for this issue
        let myValue:String
        let myOtherValue:String
}

@State private var structItems = [myStruct(myValue: "0", myOtherValue: "please select an option"),
                                      myStruct(myValue: "1", myOtherValue: "Option1"),
                                      myStruct(myValue: "2", myOtherValue: "Option2"),
                                      myStruct(myValue: "3", myOtherValue: "Option3"),
                                      myStruct(myValue: "4", myOtherValue: "Option4"),
                                      myStruct(myValue: "5", myOtherValue: "Option5")]
@State private var selectedStructItem = myStruct(myValue: "0", myOtherValue: "please select an option")


var body: some View {

Picker(selection: $selectedStructItem, label: Text(selectedStructItem.myOtherValue)) {
    ForEach(structItems, id: \.id) { val in
        Text(val.myOtherValue).tag(val)
    }
    }.onTapGesture(){
        if structItems.contains(myStruct(myValue: "0", myOtherValue: "please select an option")) {
                        structItems.remove(at: 0)
                }
    }


}
s_hasan80
  • 76
  • 4