Find city name and country from latitude and longitude in Swift

前端 未结 11 1972
既然无缘
既然无缘 2020-12-12 22:58

I\'m working on application in Swift3 and I have letter problem i can\'t find the answer for it.

How can I know city name and country short names base on latitud

11条回答
  •  孤城傲影
    2020-12-12 23:25

    You can use CLGeocoder reverseGeocodeLocation method to fetch a CLPlacemark and get its country and locality properties info. Note that it is an asynchronous method so you will need to add a completion handler to your method when fetching that info:

    import UIKit
    import MapKit
    import PlaygroundSupport
    PlaygroundPage.current.needsIndefiniteExecution = true
    
    extension CLLocation {
        func fetchCityAndCountry(completion: @escaping (_ city: String?, _ country:  String?, _ error: Error?) -> ()) {
            CLGeocoder().reverseGeocodeLocation(self) { completion($0?.first?.locality, $0?.first?.country, $1) }
        }
    }
    

    Usage

    let location = CLLocation(latitude: -22.963451, longitude: -43.198242)
    location.fetchCityAndCountry { city, country, error in
        guard let city = city, let country = country, error == nil else { return }
        print(city + ", " + country)  // Rio de Janeiro, Brazil
    }
    

    edit/update:

    iOS 11 or later CLPlacemark has a postalAddress property. You can import Contacts framework and use CNPostalAddressFormatter's string(from:) method to get a localized formatted address. You can also extend CLPlacemark and add some computed properties to better describe some of its properties:

    import MapKit
    import Contacts
    
    extension CLPlacemark {
        /// street name, eg. Infinite Loop
        var streetName: String? { thoroughfare }
        /// // eg. 1
        var streetNumber: String? { subThoroughfare }
        /// city, eg. Cupertino
        var city: String? { locality }
        /// neighborhood, common name, eg. Mission District
        var neighborhood: String? { subLocality }
        /// state, eg. CA
        var state: String? { administrativeArea }
        /// county, eg. Santa Clara
        var county: String? { subAdministrativeArea }
        /// zip code, eg. 95014
        var zipCode: String? { postalCode }
        /// postal address formatted
        @available(iOS 11.0, *)
        var postalAddressFormatted: String? {
            guard let postalAddress = postalAddress else { return nil }
            return CNPostalAddressFormatter().string(from: postalAddress)
        }
    }
    

    extension CLLocation {
        func placemark(completion: @escaping (_ placemark: CLPlacemark?, _ error: Error?) -> ()) {
            CLGeocoder().reverseGeocodeLocation(self) { completion($0?.first, $1) }
        }
    }
    

    Usage:

    let location = CLLocation(latitude: 37.331676, longitude: -122.030189)
    location.placemark { placemark, error in
        guard let placemark = placemark else { 
            print("Error:", error ?? "nil")
            return
        }
        print(placemark.postalAddressFormatted ?? "")
    }
    

    This will print

    1 Infinite Loop
    Cupertino CA 95014
    United States


提交回复
热议问题