locationManager.startUpdatingLocation gets executed too late

221 Views Asked by At

I am trying to get my user's current location using a closure, but it returns a nil value because the locationManager.startUpdatingLocation() sets the value after the closure has returned the (nil) value. I don't know how to wait for the value to get set before I return it using the closure.

This is my location layer:

  class LocationLayer: NSObject {
    static let shared = LocationLayer()
    private let locationManager = CLLocationManager()
    var location: CLLocation?

    override private init() {
        super.init()
        locationManager.delegate = self
    }

    func getCurrentLocation(completion: (CLLocation?) -> ()) {
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        if CLLocationManager.locationServicesEnabled() {
            locationManager.startUpdatingLocation()
        }
        completion(location)
    }
}

    extension LocationLayer: CLLocationManagerDelegate {
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            self.location = locations[0] as CLLocation
            manager.stopUpdatingLocation()
        }
    
        func locationManager(_ manager: CLLocationManager, didFailWithError error: Error)
        {
            print("Error \(error)")
        }
    }
1

There are 1 best solutions below

2
Shehata Gamal On

You need

1- Add this to class LocationLayer

var getLoc:(CLLocation-> ())?

2-

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
  self.location = locations[0] as CLLocation
  getLoc?(self.location)
  manager.stopUpdatingLocation()
}

Then inside where you use it do

locationLayerInstance.getLoc = { [weak self] loc in  
   print(loc)
}

3- Finally change

func getCurrentLocation(completion: (CLLocation?) -> ()) {
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestWhenInUseAuthorization()
    if CLLocationManager.locationServicesEnabled() {
        locationManager.startUpdatingLocation()
    }
    completion(location)
}

To

func startGettingLocation() {
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestWhenInUseAuthorization()
    if CLLocationManager.locationServicesEnabled() {
        locationManager.startUpdatingLocation()
    } 
}