WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

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

1      

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?
}

1      

Hacking with Swift is sponsored by Emerge

SPONSORED Optimize your app’s startup time, binary size, and overall performance using Emerge’s advanced app optimization and monitoring tools. Reliably measure app size, speed up your app's startup time with Emerge's Launch Booster, and much more. Emerge is actively used by many of the top mobile development teams in the world.

Find out 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.