I've created a custom plugin for Cordova in Swift. Generally speaking it's "working", since I'm able to communicate with it through JavaScript. Everything is fine until I try to call a method defined in one of my classes. At this moment I'm getting EXC_BAD_ACCESS error when calling locationService.authorizeLocationServices
method.
import Foundation
import CoreLocation
@objc(DBT) class DBT : CDVPlugin {
var locationService: LocationService = LocationService()
func authorizeLocationServices(_ command: CDVInvokedUrlCommand) {
let delegate = commandDelegate!
locationService.authorizeLocationServices(success: {
delegate.send(CDVPluginResult(status: CDVCommandStatus_OK, messageAs: "All OK"), callbackId:command.callbackId)
}, fail: {
delegate.send(CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Not good, not good..."), callbackId:command.callbackId)
})
}
}
class LocationService : NSObject, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
var authorizationSuccessCallback: (() -> ())?
var authorizationFailureCallback: (() -> ())?
override init() {
super.init()
locationManager.delegate = self
}
func authorizeLocationServices(success successCallback: @escaping () -> (), fail failureCallback: @escaping () -> ()) {
authorizationSuccessCallback = successCallback
authorizationFailureCallback = failureCallback
if CLLocationManager.authorizationStatus() != CLAuthorizationStatus.authorizedAlways {
locationManager.requestAlwaysAuthorization()
} else {
successCallback()
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == CLAuthorizationStatus.authorizedAlways {
if let callback = authorizationSuccessCallback {
callback()
}
} else {
if let callback = authorizationFailureCallback {
callback()
}
}
}
}
I've debugged the code, and it looks like this is caused by the locationService
instance, but I don't know why.
Eventually I've solved my issue. From unknown reason, the locationService
isn't instantiated. So I had to make it an optional type and instantiate it in a method. The code below works as expected.
import Foundation
import CoreLocation
@objc(DBT) class DBT : CDVPlugin {
var locationService: LocationService?
func authorizeLocationServices(_ command: CDVInvokedUrlCommand) {
locationService = LocationService()
if let service = locationService {
service.authorizeLocationServices(success: {
self.commandDelegate!.send(CDVPluginResult(status: CDVCommandStatus_OK, messageAs: "All OK"), callbackId:command.callbackId)
}, fail: {
self.commandDelegate!.send(CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Not good, not good..."), callbackId:command.callbackId)
})
}
}
}
class LocationService : NSObject, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
var authorizationSuccessCallback: (() -> ())?
var authorizationFailureCallback: (() -> ())?
override init() {
super.init()
locationManager.delegate = self
}
func authorizeLocationServices(success successCallback: @escaping () -> (), fail failureCallback: @escaping () -> ()) {
authorizationSuccessCallback = successCallback
authorizationFailureCallback = failureCallback
if CLLocationManager.authorizationStatus() != CLAuthorizationStatus.authorizedAlways {
locationManager.requestAlwaysAuthorization()
} else {
successCallback()
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == CLAuthorizationStatus.authorizedAlways {
if let callback = authorizationSuccessCallback {
callback()
}
} else {
if let callback = authorizationFailureCallback {
callback()
}
}
}
}