theDC
theDC

Reputation: 6484

Swift 3: reverseGeocodeLocation does not call its completion handler

This is my code

if loc.latitude != 0.0 && loc.longitude != 0.0 {
    let loca = CLLocation(latitude: loc.latitude, longitude: loc.longitude)
    geoCoder.reverseGeocodeLocation(loca) { (placemarks, error) in // this is the last line that is being called
      var placemark : CLPlacemark!
      placemark = placemarks?[0]
      city = (placemark.addressDictionary?["City"] as! String)
    }
}

Execution of this code snippet in my app goes right, no runtime errors occurred.

However, the last line that is being called is

geoCoder.reverseGeocodeLocation(loca){(placemarks, error)

I also double checked that loca is not nil.

Why completion handler is not being called?

Upvotes: 2

Views: 6072

Answers (2)

Bianco
Bianco

Reputation: 551

I came across this question and it seems as if there was some confusion regarding the answer. Here is the expansive way of getting location information using Swift 3, just for any future readers that come across this question.

This function code uses the didUpdateLocations function and reverseGeocodeLocation() to convert the location into a human readable address. It also sets the map view to the current user location. This of course is assuming you've set up your location manager object.

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

    // Get first location item returned from locations array
    let userLocation = locations[0]

    // Convert location into object with human readable address components
    CLGeocoder().reverseGeocodeLocation(userLocation) { (placemarks, error) in

        // Check for errors
        if error != nil {

            print(error ?? "Unknown Error")

        } else {

            // Get the first placemark from the placemarks array.
            // This is your address object
            if let placemark = placemarks?[0] {

                // Create an empty string for street address
                var streetAddress = ""

                // Check that values aren't nil, then add them to empty string
                // "subThoroughfare" is building number, "thoroughfare" is street
                if placemark.subThoroughfare != nil && placemark.thoroughfare != nil {

                    streetAddress = placemark.subThoroughfare! + " " + placemark.thoroughfare!

                } else {

                    print("Unable to find street address")

                }

                // Same as above, but for city
                var city = ""

                // locality gives you the city name
                if placemark.locality != nil  {

                    city = placemark.locality!

                } else {

                    print("Unable to find city")

                }

                // Do the same for state
                var state = ""

                // administrativeArea gives you the state
                if placemark.administrativeArea != nil  {

                    state = placemark.administrativeArea!

                } else {

                    print("Unable to find state")

                }

                // And finally the postal code (zip code)
                var zip = ""

                if placemark.postalCode != nil {

                    zip = placemark.postalCode!

                } else {

                    print("Unable to find zip")

                }

                print("\(streetAddress)\n\(city), \(state) \(zip)")

            }

        }

    }

    // Create a coordinate based on users location latitude and longitude
    let coordinate = CLLocationCoordinate2D(latitude: userLocation.coordinate.latitude,
                                            longitude: userLocation.coordinate.longitude)

    // Set the span (zoom) of the map view. Smaller number zooms in closer
    let span = MKCoordinateSpan(latitudeDelta: 0.001, longitudeDelta: 0.001)

    // Set the region, using your coordinates & span objects
    let region = MKCoordinateRegion(center: coordinate, span: span)

    // Set your map object's region to the region you just defined
    map.setRegion(region, animated: true)

}

Upvotes: 0

Mehul Patel
Mehul Patel

Reputation: 23053

Use completionHandler in Closure.

Check below example:

geoCoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in

            // Place details
            var placeMark: CLPlacemark!
            placeMark = placemarks?[0]

            // Address dictionary
            print(placeMark.addressDictionary, terminator: "")

            // Location name
            if let locationName = placeMark.addressDictionary!["Name"] as? NSString {
                print(locationName, terminator: "")
            }

            // Street address
            if let street = placeMark.addressDictionary!["Thoroughfare"] as? NSString {
                print(street, terminator: "")
            }

            // City
            if let city = placeMark.addressDictionary!["City"] as? NSString {
                print(city, terminator: "")
            }

            // Zip code
            if let zip = placeMark.addressDictionary!["ZIP"] as? NSString {
                print(zip, terminator: "")
            }

            // Country
            if let country = placeMark.addressDictionary!["Country"] as? NSString {
                print(country, terminator: "")
            }

        })

Upvotes: 5

Related Questions