Search code examples
iosswiftswiftui

SwiftUI Picker in Form does not show checkmark


I have a Picker embedded in Form, however I can't get it working that it shows a checkmark and the selected value in the form.

NavigationView {
    Form {
        Section {
                Picker(selection: $currencyCode, label: Text("Currency")) {
                    ForEach(0 ..< codes.count) {
                        Text(self.codes[$0]).tag($0)
                    }
                }
            }
    }
}

No checkmark and no selected value


Solution

  • TL;DR

    Your variable currencyCode does not match the type of the ID for each element in your ForEach. Either iterate over the codes in your ForEach, or pass your Picker an index.

    Below are three equivalent examples. Notice that the @State variable which is passed to Picker always matches the ID of element that the ForEach iterates over:

    Also note that I have picked a default value for the @State variable which is not in the array ("", -1, UUID()), so nothing is shown when the form loads. If you want a default option, just make that the default value for your @State variable.

    Example 1: Iterate over codes (i.e. String)

    struct ContentView: View {
        @State private var currencyCode: String = ""
        var codes: [String] = ["EUR", "GBP", "USD"]
    
        var body: some View {
            NavigationView {
                Form {
                    Section {
                        Picker(selection: $currencyCode, label: Text("Currency")) {
                            // ID is a String ----v
                            ForEach(codes, id: \.self) { (string: String) in
                                Text(string)
                            }
                        }
                    }
                }
            }
        }
    }
    

    Example 2: Iterate over indices (i.e. Int)

    struct ContentView: View {
        @State private var selectedIndex: Int = -1
        var codes: [String] = ["EUR", "GBP", "USD"]
    
        var body: some View {
            NavigationView {
                Form {
                    Section {
                        Picker(selection: $selectedIndex, label: Text("Currency")) {
                            // ID is an Int --------------v
                            ForEach(codes.indices, id: \.self) { (index: Int) in
                                Text(self.codes[index])
                            }
                        }
                    }
                }
            }
        }
    }
    

    Example 3: Iterate over an identifiable struct by its ID type (i.e. UUID)

    struct Code: Identifiable {
        var id = UUID()
        var value: String
    
        init(_ value: String) {
            self.value = value
        }
    }
    
    struct ContentView: View {
        @State private var selectedUUID = UUID()
        var codes = [Code("EUR"), Code("GBP"), Code("USD")]
    
        var body: some View {
            NavigationView {
                Form {
                    Section {
                        Picker(selection: $selectedUUID, label: Text("Currency")) {
                            // ID is a UUID, because Code conforms to Identifiable
                            ForEach(self.codes) { (code: Code) in
                                Text(code.value)
                            }
                        }
                    }
                }
            }
        }
    }