Home > Back-end >  Unable to store selected Picker value in SwiftUI
Unable to store selected Picker value in SwiftUI

Time:01-09

I have a simple SwiftUI view with a Picker containing a list of objects from a data array. The Picker lists the objects just fine, but the selected value is not being saved to the binding variable $selectedCar. It returns empty string. This is the view in question:

struct GarageSpace: View {

var currentUserID: String
@Environment(\.presentationMode) var presentationMode

@Binding var selectedPlaceID: String
@Binding var selectedPlaceName: String
@Binding var selectedPlaceDate: Date
@Binding var selectedSpaceID: String
@State var selectedCar: String
@Binding var cars: CarArrayObject

var body: some View { 
    VStack{
        Group{
            
            Picker("Car", selection: $selectedCar) {
            if let cars = cars{
                ForEach(cars.dataArray, id: \.self) {car in
                    let year = car.year! as String
                    let make = car.make as String
                    let model = car.model! as String
                    let string = year   " "   make   " "   model
                    
                    Text(string) //displays correctly in Picker
                }
            }
        }
            Spacer()
            if let cars = cars {
                Button {
                    print("yes")
                    print(selectedCar) //returns empty string
                } label: {
                    Text("Confirm")
                }
            }
        }
    }
}
}

The above view is displayed via a NavigationLink on the previous screen:

NavigationLink(destination: GarageSpace(currentUserID: currentUserID, selectedPlaceID: $selectedPlaceID, selectedPlaceName: $selectedPlaceName, selectedPlaceDate: $selectedPlaceDate, selectedSpaceID: $selectedSpaceID, selectedCar: "", cars: $cars)) {
                    
                }

This NavigationLink might be the culprit because I'm sending an empty string for selectedCar. However, it forces me to initialize a value with the NavigationLink.

Any ideas? Thanks!

EDIT: Added a tag of type String, still same outcome:

Text(string).tag(car.carID)

EDIT: FOUND THE ISSUE! However, I'm still stumped. The selection variable is empty because I wasn't pressing on the Picker since I only had one item in the array. How can I get the Picker to "select" an item if it's the only one in the array by default?

CodePudding user response:

With tag, all works well in my simple tests. Here is my test code:

import SwiftUI

@main
struct TestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
struct ContentView: View {
    var body: some View {
        GarageSpace()
    }
}
struct GarageSpace: View {
    @State var selectedCar: String = ""
    @State var cars: CarArrayObject? = CarArrayObject(car: CarModel(make: "Ford"))
    
    var body: some View {
        VStack {
            Group {
                Picker("Car", selection: $selectedCar) {
                    if let cars = cars {
                        ForEach(cars.dataArray, id: \.self) { car in
                            Text(car.make).tag(car.carID)
                        }
                    }
                }
                Spacer()
                if let cars = cars {
                    Button {
                        print("----> selectedCar carID: \(selectedCar)")
                    } label: {
                        Text("Show selected carID")
                    }
                }
            }
        }
        // optional, to select the first car
        .onAppear {
            if let cars = cars {
                selectedCar = (cars.dataArray.first != nil) ? cars.dataArray.first!.carID : ""
            }
        }
    }
    
}
struct CarModel: Hashable {
    var make = ""
    var carID = UUID().uuidString
}

class CarArrayObject: ObservableObject{
    // for testing
    @Published var dataArray = [CarModel(make: "Toyota"), CarModel(make: "Suzuki"), CarModel(make: "VW")]
    
    /// USED FOR SINGLE CAR SELECTION
    init(car: CarModel) {
        self.dataArray.append(car)
    }
    
    /// USED FOR GETTING CARS FOR USER PROFILE
    init(userID: String) {
//        print("GET CARS FOR USER ID \(userID)")
//        DataService.instance.downloadCarForUser(userID: userID) { (returnedCars) in
//
//            let sortedCars = returnedCars.sorted { (car1, car2) -> Bool in
//                return car1.dateCreated > car2.dateCreated
//            }
//            self.dataArray.append(contentsOf: sortedCars)
//        }
    }
}
  •  Tags:  
  • Related