ios – Swift CLLocationManagerDelegate never got fired


I have this silly issue where I have been debugging for a whole day:

I implemented LocationManager class to retrieve user’s coordinate, it worked last night. Then suddenly it stopped working today, I ran locationManager.startUpdatingLocation() but locationManager delegates never got fired, no result nor error. The class is a singleton so it stayed there without being destroyed, I checked locationManager.delegate and it refers my class LocationManager (not nil)

I have read almost every post about CLLocationManager and I’m desperated.

Here is my Info.plist:

    <key>NSWidgetUsesLocation</key>
    <true/>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Enable Weather for Power Users</string>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>Enable Weather for Power Users</string>

and LocationManager.swift


import Foundation
import CoreLocation

// Usage
// LocationManager.Instance.getCoordinateString(() { coordinatesString
//  print("Current coordinates string: \(coordinatesString!)")
//)

class LocationManager: NSObject, CLLocationManagerDelegate {
    static let Instance = LocationManager()
    
    private var locationManager = CLLocationManager()
    private var authorizeCompletion: (() -> Void)?
    private var updateCompletion: ((_ coordinateString: String?) -> Void)?
    
    private override init() {
        super.init()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
    }
    
    public func requestPermission(completion: @escaping () -> Void) {
        if status != .notDetermined {
            completion()
            return
        }
        
        authorizeCompletion = completion
        locationManager.requestAlwaysAuthorization()
    }
    
    public var status: CLAuthorizationStatus {
        get {
            return locationManager.authorizationStatus
        }
    }
    
    func getCoordinateString(completion: @escaping (_ coordinateString: String?) -> Void) {
        print("LocationManager.getCoordinateString() \(status)", locationManager.delegate)
        
        if status == .denied || status == .restricted {
                //          print("LocationManager.locationManager(): ERROR Permission:", status)
            completion(nil)
            return
        }
        
        if status == .notDetermined {
            completion(nil) // Temporary return basic weather
            
            requestPermission(completion: { [self] in
                updateCompletion = completion
                locationManager.startUpdatingLocation()
                    //              locationManager.requestLocation()
            })
            return
        }
        
        updateCompletion = completion
        locationManager.startUpdatingLocation()
    }
    
    // MARK: CLLocationManagerDelegate
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        print("LocationManager.locationManager(): Authorization completed", status)
        authorizeCompletion?()
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        print("LocationManager.locationManager(): didUpdateLocations")
        
        guard let location = locations.last else {
            print("LocationManager.locationManager(): ERROR No coodinate found")
            updateCompletion?(nil)
            updateCompletion = nil
            return
        }
        
        // Stop updating location after the first result
        locationManager.stopUpdatingLocation()
        
        let latitude = String(format: "%.4f", location.coordinate.latitude)
        let longitude = String(format: "%.4f", location.coordinate.longitude)
        let result = "\(latitude),\(longitude)"
        
        // Call completion handler if it's set
        updateCompletion?(result)
        updateCompletion = nil
        
        print("LocationManager.locationManager(): Coordinate \(result)")
    }
    
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("LocationManager.locationManager(): ERROR \(error.localizedDescription)")
        updateCompletion?(nil)
        updateCompletion = nil
        locationManager.stopUpdatingLocation()
    }
}

I have tested:

  • On iOS Simulators
  • On all real devices through Testflight & Xcode debugging installs
  • Even with my code reverted.

So far I have tried to create a clean project and put my LocationManager.swift and it’s working perfectly!? on iOS simulator

Another funny note that even without Info.plist keys being added, the “clean project” I tested still returns error:

LocationManager.locationManager(): ERROR The operation couldn’t be completed. (kCLErrorDomain error 1.)

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img