-->

Crash in Geocode call

2019-06-01 12:01发布

问题:

In using CLGeocoder I get a crash (EXC_BAD_ACCESS) right after the let placemark ... in the closure success part which I don't understand. I am testing and may have made tried to access the server many times. Or do I need to make the call in a background thread?

import UIKit
import CoreLocation

class ViewController: UIViewController {

var destinationPlacemark = CLPlacemark()

override func viewDidLoad() {
    super.viewDidLoad()
    forwardGeocoding(address: "Infinite Loop, Cupertino, CA 95014")
}

func forwardGeocoding(address: String) {
    CLGeocoder().geocodeAddressString(address, completionHandler: { (placemarks, error) in
        if error != nil {
            print(error ?? "Error in plscement conversion")
            return
        }
        if (placemarks?.count)! > 0 {
            let placemark = placemarks?[0]
            let location = self.destinationPlacemark.location
            let coordinate = location?.coordinate
            print("Latitude: \(coordinate!.latitude), Longitude: \(coordinate!.longitude)")

            self.destinationPlacemark = placemark!
        }
    })
}

}

回答1:

*Updated with cause *

You had quite a few things here, so I will try to step through the changes I made to fix it:

First, why it crashes:

You create your destinationPlacemark with the following command:

var destinationPlacemark = CLPlacemark()

So when this runs:

let location = self.destinationPlacemark.location

It is running against an empty placemark that contains no location data. By pulling the location from the retrieved placemark created in the guard statement, this issue is avoided.

Next, the working code:

import UIKit
import CoreLocation

class ViewController: UIViewController {

    var destinationPlacemark: CLPlacemark?

    override func viewDidLoad() {
        super.viewDidLoad()
        forwardGeocoding(address: "1 Infinite Loop, Cupertino, CA 95014")
    }

    func forwardGeocoding(address: String) {
        CLGeocoder().geocodeAddressString(address, completionHandler: { (placemarks, error) in
            if error != nil {
                print(error ?? "Error in pla conversion")
                return
            }

            guard let placemark = placemarks?.first, let coordinate = placemark.location?.coordinate else { return }
            print("Latitude: \(coordinate.latitude), Longitude: \(coordinate.longitude)")

            self.destinationPlacemark = placemark
        })
    }

}

Which produces:

Latitude: 37.3316941, Longitude: -122.030127
  1. You do not set up the variable for destinationPlacemark properly, see the above for a proper setup
  2. Your address for Apple is wrong, I added a 1 to the front, though you still get a value
  3. You are forcing too many items, which leads to crashes as you saw. I replaced your forced casts with a guard statement to prevent those
  4. I de-clutttered some variables in your success section to streamline the code