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)
// }
}
}
