Search code examples
swiftxcodeswiftuipicker

Why does this SwiftUI Picker code not work?


Xcode: 11.2.1

The code below is for a simple form with two components; a Picker (to select a letter) and a Text (to display the selected letter). The code compiles and runs but, when a letter is selected it does not appear in the "Selected..." text. In addition, Xcode displays a (spurious?) run time warning the first time (only) a letter is selected..

struct ContentView: View {

    @State private var letter = ""
    private let letters = ["Alpha", "Bravo", "Charlie"]

    var body: some View {
        NavigationView {
            Form {
                Picker("Select a letter", selection: $letter) {
                    ForEach(0..<letters.count) {
                        Text(self.letters[$0])
                    }
                }
                Text("Selected letter: \(letter)")
            }
            .navigationBarTitle("Main Menu")
        }
    }
}

For info: the run time warning:

[TableView] Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window). This may cause bugs by forcing views inside the table view to load and perform layout without accurate information (e.g. table view bounds, trait collection, layout margins, safe area insets, etc), and will also cause unnecessary performance overhead due to extra layout passes. Make a symbolic breakpoint at UITableViewAlertForLayoutOutsideViewHierarchy to catch this in the debugger and see what caused this to occur, so you can avoid this action altogether if possible, or defer it until the table view has been added to a window. Table view: <_TtC7SwiftUIP33_BFB370BA5F1BADDC9D83021565761A4925UpdateCoalescingTableView: 0x7f8b33872600; baseClass = UITableView; frame = (0 0; 414 896); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = ; layer = ; contentOffset: {0, -140}; contentSize: {414, 205.33333333333337}; adjustedContentInset: {140, 0, 34, 0}; dataSource: <_TtGC7SwiftUIP10$10f5cd23419ListCoreCoordinatorGVS_20SystemListDataSourceOs5Never_GOS_19SelectionManagerBoxS2___: 0x7f8b33407a70>>


Solution

  • ForEach types inside Picker should be aligned with selection type.

    Here is a corrected code that should work for you:

    @State private var letter = ""
    private let letters = ["Alpha", "Bravo", "Charlie"]
    
    var body: some View {
        NavigationView {
            Form {
                Picker("Select a letter", selection: $letter) {
                    ForEach(letters, id: \.self) { option in
                        Text(option)
                    }
                }
                Text("Selected letter: \(letter)")
            }
            .navigationBarTitle("Main Menu")
        }
    }