I implemented a class conforming to CLLocationManagerDelegate with the singleton pattern. Calling requestWhenInUseAuthorization (i.e. requestPermission() in the code below) propts the user to accept, as expected. However, locationManagerDidChangeAuthorization(_ manager: CLLocationManager) is not always called once the user taps “Allow once”.
I have not found any pattern when it is called and when not, it seems very inconsistent (It is never called on the first time ever called for each fresh app download. This happens both on a real device as well as the simulator.
When I implement a function forceInit() and call it very early in my app, all works well. Thus I assume this is caused by the Singleton being lazily initialised, and somehow the delegate function not being called if the singleton initialises “too late”.
Am I doing something wrong? Why would I need to initialise the Singleton early, when it is being initialised anyways when needed by the requestPermission() call?
class LocationService: NSObject, CLLocationManagerDelegate {
static var shared: LocationService = LocationService()
@Published private(set) var authorizationStatus: CLAuthorizationStatus
private let clLocationManager: CLLocationManager
public override init() {
clLocationManager = CLLocationManager()
authorizationStatus = clLocationManager.authorizationStatus
super.init()
clLocationManager.delegate = self
clLocationManager.desiredAccuracy = kCLLocationAccuracyBest
clLocationManager.startUpdatingLocation()
}
func forceInit() { // why do I need this? I would rather not explicitly initialise...
authorizationStatus = clLocationManager.authorizationStatus
}
func requestPermission() {
self.clLocationManager.requestWhenInUseAuthorization()
}
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
print("AAA NEW AUTH: \(manager.authorizationStatus)") // not printed unless forceInit() is called right on app launch
self.authorizationStatus = manager.authorizationStatus
// TODO
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let newLocation: CLLocation = locations.first else { return }
// do sth
}
}




