0

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?

9
  • I think you need to tag them for the selection to work. Commented Jan 8, 2022 at 23:03
  • I changed it to Text(string).tag(car.id) and still get an empty string. Thanks though Commented Jan 8, 2022 at 23:23
  • is car.id a String? The tag need to match the selectedCar: String in type. Commented Jan 9, 2022 at 0:18
  • car.id is a UUID, I changed the tag to use a String instead but I'm still getting a blank. p car.carID (String) $R0 = "N2cl4SD47PBWGjDrei2p" is what I get when I put a breakpoint within the ForEach loop for the Picker Commented Jan 9, 2022 at 1:05
  • 1
    try adding this to the VStack: .onAppear { if let cars = cars { selectedCar = (cars.dataArray.first != nil) ? cars.dataArray.first!.carID : "" } } Commented Jan 9, 2022 at 2:02

1 Answer 1

1

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) // } } } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.