0

I am trying to set up a function to get my current location in app delegate but when I print(city) at the bottom it returns the original initialized value in the global variable which is "hello", even though I updated the value under the CLGeocoder.

AppDelegate:

    import UIKit
    import CoreData
    import CoreLocation

    let appDelegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate

    var country = "hello"
    var city = "hello"

 func setupLocationManager(){
        let locationManager = CLLocationManager()
        locationManager.requestAlwaysAuthorization()
        locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        locationManager.startUpdatingLocation()
    }

    // Below method will provide you current location.
    func getLocation() -> [String]{
        let manager = CLLocationManager()
        manager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        manager.requestAlwaysAuthorization()
        manager.startUpdatingLocation()

        manager.desiredAccuracy = kCLLocationAccuracyBest
        manager.requestAlwaysAuthorization()
        manager.startUpdatingLocation()

        let selflocation = manager.location

        let latitude: Double = selflocation!.coordinate.latitude
        let longitude: Double = selflocation!.coordinate.longitude


        print("current latitude :: \(latitude)")
        print("current longitude :: \(longitude)")

        let location = CLLocation(latitude: latitude, longitude: longitude) //changed!!!            

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

            if error != nil {
                print("Reverse geocoder failed with error" + (error?.localizedDescription)!)
            }

            let pm = placemarks![0]
            let speed = (selflocation?.speed)!
            city = pm.addressDictionary!["City"]! as! String
            country = pm.addressDictionary!["Country"]! as! String

            if (placemarks?.count)! > 0 {
            }
            else {
                print("Problem with the data received from geocoder")
            }
        })

        print(city)
        return [city as! String, country as! String]
    }
Borys Verebskyi
  • 4,160
  • 6
  • 28
  • 42

4 Answers4

1

This is because the geocoding is done asynchronously, so the print(city) is being executed before the geocoding is completed. So I suggest you do this.

func getLocation(completion: @escaping (Array<String>)->()){

    let manager = CLLocationManager()

    manager.desiredAccuracy = kCLLocationAccuracyBest

    manager.requestAlwaysAuthorization()

    manager.startUpdatingLocation()

    let selflocation = manager.location

    let latitude: Double = selflocation!.coordinate.latitude

    let longitude: Double = selflocation!.coordinate.longitude

    let location = CLLocation(latitude: latitude, longitude: longitude)

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

        if let error = error {

            print(error.localizedDescription)

            return
        }

        if let placemark = placemarks?.first {

            if let country = placemark.country, let city = placemark.locality {

                completion([city, country])

                return

            } else {

                print("country or city was nil.")
            }
        } else {

            print("Problem with the data received from geocoder")
        }
    })
}

So instead of calling getLocation() call

getLocation { (location) in

    print(location)
}
Tristan Beaton
  • 1,742
  • 2
  • 14
  • 25
1

The problem here is you are getting the value before a new location value is assigned to it. You have to wait a little bit to get the updated value.

Zohaib Hassan
  • 984
  • 2
  • 7
  • 11
0

reverseGeocodeLocation works asynchronously, so the print statement is actually happening before it finishes. If you have any logic that depends on the results, you'll probably need to put it inside the completion handler closure.

John Montgomery
  • 6,739
  • 9
  • 52
  • 68
0

Like the other answer says, reverseGeocodeLocation works asynchronously, so you may want to move the print(city) inside the closure, such as after

else {
    print("Problem with the data received from geocoder")
}
RPatel99
  • 7,448
  • 2
  • 37
  • 45
  • Moving print(city) inside the closure will print out the correct response, however, you cannot return a function within a closure, so this will not work. – Tristan Beaton May 09 '17 at 22:18