Convert coordinates to City name? Convert coordinates to City name? ios ios

Convert coordinates to City name?



SWIFT 4.2 : EDIT


MapKit framework does provide a way to get address details from coordinates.

You need to use reverse geocoding of map kit. CLGeocoder class is used to get the location from address and address from the location (coordinates). The method reverseGeocodeLocation will returns the address details from coordinates.

This method accepts CLLocation as a parameter and returns CLPlacemark, which contains address dictionary.

So now above method will be updated as:

@objc func didLongPressMap(sender: UILongPressGestureRecognizer) {    if sender.state == UIGestureRecognizer.State.began {        let touchPoint = sender.location(in: mapView)        let touchCoordinate = mapView.convert(touchPoint, toCoordinateFrom: self.mapView)        let annotation = MKPointAnnotation()        annotation.coordinate = touchCoordinate        annotation.title = "Your position"        mapView.addAnnotation(annotation) //drops the pin        print("lat:  \(touchCoordinate.latitude)")        let num = touchCoordinate.latitude as NSNumber        let formatter = NumberFormatter()        formatter.maximumFractionDigits = 4        formatter.minimumFractionDigits = 4        _ = formatter.string(from: num)        print("long: \(touchCoordinate.longitude)")        let num1 = touchCoordinate.longitude as NSNumber        let formatter1 = NumberFormatter()        formatter1.maximumFractionDigits = 4        formatter1.minimumFractionDigits = 4        _ = formatter1.string(from: num1)        self.adressLoLa.text = "\(num),\(num1)"        // Add below code to get address for touch coordinates.        let geoCoder = CLGeocoder()        let location = CLLocation(latitude: touchCoordinate.latitude, longitude: touchCoordinate.longitude)        geoCoder.reverseGeocodeLocation(location, completionHandler:            {                placemarks, error -> Void in                // Place details                guard let placeMark = placemarks?.first else { return }                // Location name                if let locationName = placeMark.location {                    print(locationName)                }                // Street address                if let street = placeMark.thoroughfare {                    print(street)                }                // City                if let city = placeMark.subAdministrativeArea {                    print(city)                }                // Zip code                if let zip = placeMark.isoCountryCode {                    print(zip)                }                // Country                if let country = placeMark.country {                    print(country)                }        })    }}


For Swift 3: and Swift 4

First you need to set allowance to receive User's GPS in the info.plist.

enter image description here

Set: NSLocationWhenInUseUsageDescription with a random String.And/or: NSLocationAlwaysUsageDescription with a random String.

Then I have set up a class to get the desired data like zip, town, country...:

import Foundationimport MapKittypealias JSONDictionary = [String:Any]class LocationServices {    let shared = LocationServices()    let locManager = CLLocationManager()    var currentLocation: CLLocation!    let authStatus = CLLocationManager.authorizationStatus()    let inUse = CLAuthorizationStatus.authorizedWhenInUse    let always = CLAuthorizationStatus.authorizedAlways    func getAdress(completion: @escaping (_ address: JSONDictionary?, _ error: Error?) -> ()) {        self.locManager.requestWhenInUseAuthorization()        if self.authStatus == inUse || self.authStatus == always {            self.currentLocation = locManager.location            let geoCoder = CLGeocoder()            geoCoder.reverseGeocodeLocation(self.currentLocation) { placemarks, error in                if let e = error {                    completion(nil, e)                } else {                    let placeArray = placemarks as? [CLPlacemark]                    var placeMark: CLPlacemark!                    placeMark = placeArray?[0]                    guard let address = placeMark.addressDictionary as? JSONDictionary else {                        return                    }                    completion(address, nil)                }            }        }    }}

Called by:

import UIKitclass ViewController: UIViewController {    override func viewDidLoad() {        super.viewDidLoad()        LocationServices.shared.getAdress { address, error in            if let a = address, let city = a["City"] as? String {               //            }        }    }}

Done


import Foundationimport CoreLocationimport PlaygroundSupportPlaygroundPage.current.needsIndefiniteExecution = truelet location = CLLocation(latitude: 37.3321, longitude: -122.0318)CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in        guard let placemark = placemarks?.first else {        let errorString = error?.localizedDescription ?? "Unexpected Error"        print("Unable to reverse geocode the given location. Error: \(errorString)")        return    }        let reversedGeoLocation = ReversedGeoLocation(with: placemark)    print(reversedGeoLocation.formattedAddress)    // Apple Inc.,    // 1 Infinite Loop,    // Cupertino, CA 95014    // United States}struct ReversedGeoLocation {    let name: String            // eg. Apple Inc.    let streetNumber: String    // eg. 1    let streetName: String      // eg. Infinite Loop    let city: String            // eg. Cupertino    let state: String           // eg. CA    let zipCode: String         // eg. 95014    let country: String         // eg. United States    let isoCountryCode: String  // eg. US        var formattedAddress: String {        return """        \(name),        \(streetNumber) \(streetName),        \(city), \(state) \(zipCode)        \(country)        """    }        // Handle optionals as needed    init(with placemark: CLPlacemark) {        self.name           = placemark.name ?? ""        self.streetName     = placemark.thoroughfare ?? ""        self.streetNumber   = placemark.subThoroughfare ?? ""        self.city           = placemark.locality ?? ""        self.state          = placemark.administrativeArea ?? ""        self.zipCode        = placemark.postalCode ?? ""        self.country        = placemark.country ?? ""        self.isoCountryCode = placemark.isoCountryCode ?? ""    }}

Old/Deprecated answer:

Thanks to @Kampai's answer, here's a Swift 3 compatible and safer way (no forcing !):

let geoCoder = CLGeocoder()let location = CLLocation(latitude: touchCoordinate.latitude, longitude: touchCoordinate.longitude)geoCoder.reverseGeocodeLocation(location, completionHandler: { placemarks, error in    guard let addressDict = placemarks?[0].addressDictionary else {        return    }        // Print each key-value pair in a new row    addressDict.forEach { print($0) }        // Print fully formatted address    if let formattedAddress = addressDict["FormattedAddressLines"] as? [String] {        print(formattedAddress.joined(separator: ", "))    }        // Access each element manually    if let locationName = addressDict["Name"] as? String {        print(locationName)    }    if let street = addressDict["Thoroughfare"] as? String {        print(street)    }    if let city = addressDict["City"] as? String {        print(city)    }    if let zip = addressDict["ZIP"] as? String {        print(zip)    }    if let country = addressDict["Country"] as? String {        print(country)    }})

Don't forget NSLocationWhenInUseUsageDescription and NSLocationAlwaysUsageDescription keys