I am trying to get location. Issue is that func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) and locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) are never called.
I am asked for permission. I grant it. When I call startLocation second time:
DispatchQueue.global(qos: .background).async {
let gpsController = GPSController()
gpsController.startLocation()
sleep(10)
DispatchQueue.main.async {
gpsController.startLocation()
}
}
I can see that permission is granted.
import Foundation
import CoreLocation
class GPSController : NSObject, CLLocationManagerDelegate{
let locationManager: CLLocationManager = CLLocationManager()
static var lastLocation : CLLocation? = nil
func startLocation(){
locationManager.delegate = self
// Sprawdź status usług lokalizacyjnych
if CLLocationManager.locationServicesEnabled() {
switch locationManager.authorizationStatus {
case .notDetermined:
print("notDetermined")
locationManager.requestWhenInUseAuthorization()
break
case .restricted, .denied:
print("Denied")
break
case .authorizedWhenInUse, .authorizedAlways:
locationManager.startUpdatingLocation()
print("authorizedWhenInUse")
case .authorized:
print("authorized")
break
@unknown default:
print("@unknown")
break
}
} else {
print("turn off")
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
print("didChangeAuthorization")
if manager.authorizationStatus == .authorizedWhenInUse {
locationManager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("didChangeAuthorization")
for currentLocation in locations{
Loge("Location : \(currentLocation)")
GPSController.lastLocation = currentLocation
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("error")
}
}
You're putting GPSController
inside a global queue, so the scope of the controller does not escape from the queue. After the queue is executed, the controller will be removed. And it no longer listens to that delegate
. You can check it by deinit
, it will print out after sleep(10)
.
class GPSController : NSObject, CLLocationManagerDelegate {
deinit {
print("Released")
}
}
To resolve: put the GPSController
, i.e within a class/controller, to keep a reference.
class ViewController: UIViewController {
let gpsController = GPSController()
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.global(qos: .background).async {
gpsController.startLocation()
sleep(10)
DispatchQueue.main.async {
gpsController.startLocation()
}
}
}
}
Btw, the delegate should be assigned once, so I would prefer to put it in init
convenience init() {
self.init()
locationManager.delegate = self
}