NEW: Learn to build the incredible iOS 15 Weather app today! >>

Picker With Variables Of Cities With Coordinates

Forums > Swift

I am looking to have a picker that picks cities that have coordinates and when the city is chosen the coordinates in the variable get passed to a line of code (as doubles)

here is my code:

import SwiftUI

struct CityChoose: View {
    @State private var selectedCity = "Toronto"
    var Cities = [
        City(city: "Toronto", latitude: 43.651070, longitude: 79.347015, description: "Toronto City Chosen"),
        City(city: "Al Ain", latitude: 24.207500, longitude: 55.744720, description: "Toronto City Chosen"),
        City(city: "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) { Cities in
                                Text("\(Cities.city)")
                            }
                        }
                    }
                }
            }
            .navigationTitle("Pick Your City")
        }
    }
}

struct City: Identifiable {
    let id = UUID() // useful for common SwiftUI display
    let city: 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?
}

struct CityChoose_Previews: PreviewProvider {
    static var previews: some View {
        CityChoose()
    }
} 

this code makes the picker work but when the city is clicked it doesnt actually choose it

I want it when it is chosen the coordinates are passed to a line of code like this

let coordinates = Coordinates(latitude: 33.383293, longitude: -118.433304)

let me know if there are any clarifications needed

   

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.

  1. 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.
  2. 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.
  3. 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?
}

   

Hacking with Swift is sponsored by Sentry

SPONSORED With Sentry’s error and performance monitoring for iOS, you see mobile vitals that actually matter, can solve any latency issues quickly, and learn how each release is performing over time.

Learn More

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.