Search code examples
iosswiftclgeocoder

If statement is not changing global variable swift


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]
    }

Solution

  • 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)
    }