It's because the state variable you are using to hold the selected value is a String
but you are using an array of City
in the ForEach
. Since those types don't match, you need to explicitly add a tag
to each item in the loop. Like so:
Picker("Please Choose Your City", selection: $selectedCity) {
ForEach(Cities) { Cities in
Text("\(Cities.city)").tag(Cities.city)
}
}
And, if I may, you should do some renaming of your variables.
- The convention in Swift is to name types starting with a capital letter and variables starting with a lowercase letter. So your
Cities
array should be cities
.
- The parameter you are passing into the closure of the
ForEach
is just one city, so don't give it a plural name. And along the same lines as point 1 above, it should be lowercased. So city
instead of Cities
.
- Your
City
struct looks good, except for the city
property; we already know this struct is describing a city and this property contains the name of that city, so call it what it is: name
.
(If it were my code, I would probably rename the View
something besides CityChoose
. Maybe CityChooser
or CityPicker
or whatnot, but that's up to you.)
These changes will make your code easier to read and understand, both for others—like when you post here—and for yourself in the future. Plus, by following the convention, people looking at your code for the first time can instantly understand what is a type and what is a variable without having to do mental work to figure it out.
Here's what it looks like after I implemented the suggested changes:
struct CityChoose: View {
@State private var selectedCity = "Toronto"
var cities = [
City(name: "Toronto", latitude: 43.651070, longitude: 79.347015, description: "Toronto City Chosen"),
City(name: "Al Ain", latitude: 24.207500, longitude: 55.744720, description: "Toronto City Chosen"),
City(name: "London", latitude: 51.509865, longitude: -0.118092, description: "Toronto City Chosen")
]
var body: some View {
NavigationView {
Form {
Section {
VStack {
Picker("Please Choose Your City", selection: $selectedCity) {
ForEach(cities) { city in
Text("\(city.name)").tag(city.name)
}
}
}
}
}
.navigationTitle("Pick Your City")
}
}
}
struct City: Identifiable {
let id = UUID() // useful for common SwiftUI display
let name: String // Toronto, Naples, Berlin, etc.
let latitude: Double // What's the best format to
let longitude: Double // store latitude and longitude?
let description: String // maybe a few sentences?
}