Reverse geocoding in Swift 4

前端 未结 2 1533
佛祖请我去吃肉
佛祖请我去吃肉 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条回答
  •  Happy的楠姐
    2020-12-05 21:19

    There are so many questions dealing with 'reverseGeocodeLocation' on Stack Overflow, I've seen so many of them. I'm using Swift 4.2 and I thought my 'reverseGeocodeLocation' requests might be timing out. Well, this is NOT the case, when starting to move with an iPhone the 'didUpdateLocations' cycles need to mature. It can take two or more cycles before 'reverseGeocodeLocation' returns placemarks.

    I wrote a simple app that uses 'reverseGeocodeLocation' until 'placemarks' are returned after repeated 'didUpdateLocations' cycles. This is my own home grown 'SampleCode'. I learned a lot from using the app, it might help others understand how reverse geocode requests work in the real world.

    Please give your comments on possible improvements. This code is freely given and freely taken.

    import Foundation
    import UIKit
    import CoreLocation
    
    class ViewController: UIViewController, CLLocationManagerDelegate {
        @IBAction func RefreshLocationButton(_ sender: Any) {
            self.requestingPlacemark = true
            self.placemarkData = nil
            //^Make another Placemark Request
            self.requestCounter = 0
            self.RequestCounterLabel.text = ""
            self.LocationLabel.text = ""
            self.PlacemarkLabel.text = ""}
        @IBOutlet weak var LocationCounterLabel: UILabel!
        @IBOutlet weak var RequestCounterLabel: UILabel!
        @IBOutlet weak var LocationLabel: UILabel!
        @IBOutlet weak var PlacemarkLabel: UILabel!
        let locationManager = CLLocationManager()
        var placemarkData: CLPlacemark!
        var placemarkString: String!
        var printPlacemarkData: Bool!
        var didUpdateLocationsCounter: Int = 0
        var requestCounter: Int = 0
        var requestingPlacemark: Bool = true
    
    override func viewDidLoad() {
        super.viewDidLoad()
        if CLLocationManager.locationServicesEnabled() {
            locationManager.requestAlwaysAuthorization()
            locationManager.delegate = self
            //locationManager.desiredAccuracy = kCLLocationAccuracyBest
            locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
            locationManager.startUpdatingLocation()
            self.RequestCounterLabel.text = ""
            self.LocationLabel.text = ""
            self.PlacemarkLabel.text = ""}}
    func printPlacemarks() {
        if printPlacemarkData {
            self.placemarkString = "Placemark Data:"
            self.placemarkString = buildPlacemarkString(item: 1)
            self.placemarkString = buildPlacemarkString(item: 2)
            self.placemarkString = buildPlacemarkString(item: 3)
            self.placemarkString = buildPlacemarkString(item: 4)
            self.placemarkString = buildPlacemarkString(item: 5)
            self.placemarkString = buildPlacemarkString(item: 6)
            self.placemarkString = buildPlacemarkString(item: 7)
            self.placemarkString = buildPlacemarkString(item: 8)
            self.placemarkString = buildPlacemarkString(item: 9)
            self.placemarkString = buildPlacemarkString(item: 10)
            self.PlacemarkLabel.text = self.placemarkString
            self.printPlacemarkData = false}}
    func buildPlacemarkString(item: Int) -> String {
        var elementText: String!
        var newString: String!
            switch item {
            case 1: elementText = "name: " + self.placemarkData.name!
            case 2: elementText = "subThoroughfare: " + self.placemarkData.subThoroughfare!
            case 3: elementText = "thoroughfare: " + self.placemarkData.thoroughfare!
            case 4: elementText = "postalCode: " + self.placemarkData.postalCode!
            case 5: elementText = "subLocality: " + self.placemarkData.subLocality!
            case 6: elementText = "locality: " + self.placemarkData.locality!
            case 7: elementText = "subAdministrativeArea: " + self.placemarkData.subAdministrativeArea!
            case 8: elementText = "administrativeArea: " + self.placemarkData.administrativeArea!
            case 9: elementText = "country: " + self.placemarkData.country!
            case 10: elementText = "isoCountryCode: " + self.placemarkData.isoCountryCode!
            default: print("Error: incorrect item number!")}
            newString = self.placemarkString + "\n" + elementText
        return newString
    }
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            //location prints one time and 'didUpdateLocations' is stopped:
        self.didUpdateLocationsCounter = self.didUpdateLocationsCounter + 1
        let labelString = String(describing: self.didUpdateLocationsCounter)
        self.LocationCounterLabel.text = "Location Update Counter: " + labelString
        if self.placemarkData == nil {
            //location variable:
            self.requestCounter = self.requestCounter + 1
            let textString = String(describing: self.requestCounter)
            self.RequestCounterLabel.text = "Request Counter: " + textString
            if locations.count == 0 {
                self.LocationLabel.text = "Locations: There was NONE"}
            else {
                if locations.count > 0 {
                    let coordinate2D: CLLocation = locations.first!
                    let location = CLLocation(latitude: coordinate2D.coordinate.latitude, longitude: coordinate2D.coordinate.longitude)
                    let printString = String(describing: location)
                    self.LocationLabel.text = "Location: " + printString
                    let geocoder: CLGeocoder = CLGeocoder()
                    geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in
                        if error != nil {
                            let errorString = String(describing: error?.localizedDescription)
                            print("reverse geodcode fail: \(errorString)")
                            self.LocationCounterLabel.text = ""
                            self.RequestCounterLabel.text = ""
                            self.LocationLabel.text = "Reverse Geodcode fail: \(errorString)"
                            self.PlacemarkLabel.text = ""
                            self.requestingPlacemark = false
                            return}
                        else {
                            let pm = placemarks! as [CLPlacemark]
                            //There is ALWAYS 'placemarks' Data
                            if pm.count > 0 {
                                self.placemarkData = placemarks![0]
                                self.printPlacemarkData = true
                                self.printPlacemarks()
                                self.requestingPlacemark = false}}})}
                else {
                    if self.requestingPlacemark {
                        self.LocationLabel.text = "Problem: There is no 'location.first'"}}}}}}
    

    And then the Storyboard UI:

    Storyboard Image

    View Controller Image

    
    
        
            
        
        
            
            
            
            
        
        
            
            
                
                    
                        
                            
                            
                            
                                
                                
                                
                                
                                
                            
                            
                            
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                            
                            
                        
                        
                            
                            
                            
                            
                        
                    
                    
                
                
            
        
    
    

提交回复
热议问题