Reverse geocoding in Swift 4

前端 未结 2 1531
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-05 20:19

I\'m attempting to write a simple method that\'s fed CLLocationDegrees and returns a CLPlacemark. Looking at Apple\'s documentation, it seems like

2条回答
  •  离开以前
    2020-12-05 20:53

    import UIKit
    import CoreLocation
    import PlaygroundSupport
    PlaygroundPage.current.needsIndefiniteExecution = true
    

    func geocode(latitude: Double, longitude: Double, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  {
        CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude)) { placemark, error in
            guard let placemark = placemark, error == nil else {
                completion(nil, error)
                return
            }
            completion(placemark, nil)
        }
    }
    

    or simply:

    func geocode(latitude: Double, longitude: Double, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  {
        CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude), completionHandler: completion)
    }
    

    or extending CLLocation:

    extension CLLocation {
        func geocode(completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  {
            CLGeocoder().reverseGeocodeLocation(self, completionHandler: completion)
        }
    }
    

    To format your place mark as a mailing address you can use Contacts framework CNPostalAddressFormatter:

    import Contacts
    
    extension Formatter {
        static let mailingAddress: CNPostalAddressFormatter = {
            let formatter = CNPostalAddressFormatter()
            formatter.style = .mailingAddress
            return formatter
        }()
    }
    
    extension CLPlacemark {
        var mailingAddress: String? {
            return postalAddress?.mailingAddress
        }
    }
    
    extension CNPostalAddress {
        var mailingAddress: String {
            return Formatter.mailingAddress.string(from: self)
        }
    }
    

    placemark

    Contains an array of CLPlacemark objects. For most geocoding requests, this array should contain only one entry. However, forward-geocoding requests may return multiple placemark objects in situations where the specified address could not be resolved to a single location. If the request was canceled or there was an error in obtaining the placemark information, this parameter is nil.

    For more information about the CLPlacemark properties you can check this CLPlacemark


    Usage:

    let location = CLLocation(latitude: -22.963451, longitude: -43.198242)
    location.geocode { placemark, error in
        if let error = error as? CLError {
            print("CLError:", error)
            return
        } else if let placemark = placemark?.first {
            // you should always update your UI in the main thread
            DispatchQueue.main.async {
                //  update UI here
                print("name:", placemark.name ?? "unknown")
    
                print("address1:", placemark.thoroughfare ?? "unknown")
                print("address2:", placemark.subThoroughfare ?? "unknown")
                print("neighborhood:", placemark.subLocality ?? "unknown")
                print("city:", placemark.locality ?? "unknown")
    
                print("state:", placemark.administrativeArea ?? "unknown")
                print("subAdministrativeArea:", placemark.subAdministrativeArea ?? "unknown")
                print("zip code:", placemark.postalCode ?? "unknown")
                print("country:", placemark.country ?? "unknown", terminator: "\n\n")
    
                print("isoCountryCode:", placemark.isoCountryCode ?? "unknown")
                print("region identifier:", placemark.region?.identifier ?? "unknown")
    
                print("timezone:", placemark.timeZone ?? "unknown", terminator:"\n\n")
    
                // Mailind Address
                print(placemark.mailingAddress ?? "unknown")
            }
        }
    }
    

    This will print

    name: Morro da Saudade
    address1: Rua Casuarina
    address2: 597
    neighborhood: Lagoa
    city: Rio de Janeiro
    state: RJ
    subAdministrativeArea: unknown
    zip code: 22011-040
    country: Brazil
    
    isoCountryCode: BR
    region identifier: <-22.96345100,-43.19824200> radius 141.83
    timezone: America/Sao_Paulo (current)
    

    Rua Casuarina, 597

    Lagoa

    Rio de Janeiro RJ

    22011-040

    Brazil

提交回复
热议问题