I have a separate class named LocationService
class LocationService: NSObject, CLLocationManagerDelegate {
private var locationManager = CLLocationManager()
private var locationCallback: ((CLLocation?) -> Void)!
override init(){
super.init()
self.locationManager.delegate = self
}
public func getCurrentLocation (_ completion: @escaping(CLLocation?) -> Void) {
if PermissionManager.hasLocationPermission() && CLLocationManager.locationServicesEnabled() {
self.locationCallback = completion
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.startUpdatingLocation()
} else {
completion(nil)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("LOCATIONS: ", locations)
locationCallback(locations.first)
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("LOCATION ERROR: ", error)
locationCallback(nil)
}
func locationManager(manager: CLLocationManager!, didUpdateToLocation newLocation: CLLocation!, fromLocation oldLocation: CLLocation!) {
print("LOCATION: ", newLocation)
locationCallback(newLocation)
}
deinit {
print("DEINIT LOCATION SERVICE")
}
}
If I trigger getCurrentLocation
, none of the location manager delegate functions were called, although startUpdatingLocation
was reached.
I have no view controller because it's inside a react native plugin. The Location When In Use Usage Description is set in the info.plist and the deinit function was never called. Furthermore, the location permission is also granted.
Does someone know what is missing?
CodePudding user response:
protocol LocationManagerDelegate {
func didAuthorized()
func didUpdateLocation(location: CLLocation?, isFirst: Bool)
}
final class LocationManager: NSObject {
static let shared = LocationManager()
let delegates = MulticastDelegate<LocationManagerDelegate>()
private var locationManager = CLLocationManager()
var currentLocation: CLLocation?
var isStop = false
var denied = false
override init() {
super.init()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
}
}
func request() {
if CLLocationManager.locationServicesEnabled() {
switch CLLocationManager.authorizationStatus() {
case .notDetermined, .restricted, .denied:
self.denied = true
self.locationManager.requestWhenInUseAuthorization()
case .authorizedAlways, .authorizedWhenInUse:
self.isStop = false
self.denied = false
self.locationManager.startUpdatingLocation()
default:
break
}
}
}
func stop() {
self.isStop = true
self.locationManager.stopUpdatingLocation()
}
}
This is extension
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse || status == .authorizedAlways {
self.isStop = false
if self.denied {
self.denied = false
self.locationManager.startUpdatingLocation()
self.locationManager.requestAlwaysAuthorization()
}
self.delegates.invoke(invocation: { $0.didAuthorized() })
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.first, isStop == false else {
return
}
var isFirst = false
if self.currentLocation == nil {
isFirst = true
}
self.currentLocation = location
self.delegates.invoke(invocation: { $0.didUpdateLocation(location: location, isFirst: isFirst) })
}
func checkLocationPermission() -> Bool {
// check the permission status
switch CLLocationManager.authorizationStatus() {
case .authorizedAlways, .authorizedWhenInUse:
return true
default:break
}
return false
}
}
maybe you must use this: static let shared = LocationManager()
when I want location , I use: LocationManager.shared.request()
this works for me
CodePudding user response:
First you must ask permission from user
self.locationManager.requestWhenInUseAuthorization()