I'm trying to implement the CLLocationManagerDelegate
protocol requirements via a protocol extension, but the location manager doesn't see it in the protocol extension and fails. However, it works with the same code when moved into the class.
Here's what I'm doing:
class ViewController: UIViewController, MyLocationProtocol {
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
locationManager.distanceFilter = 1000.0
locationManager.delegate = self
// Below crashes when implementation in protocol extension
locationManager.requestLocation()
}
}
protocol MyLocationProtocol: CLLocationManagerDelegate {
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
}
extension MyLocationProtocol /*where Self: UIViewControll*/ { // Tried using where clause but still no go :(
// Not being triggered by CLLocationManagerDelegate! :(
// Move to ViewController class and error goes away
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("MyLocationProtocol: locationManager: didUpdateLocations")
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("MyLocationProtocol: locationManager: didFailWithError")
}
}
Notice in extension MyLocationProtocol
I'm putting the didUpdateLocations
and didFailWithError
implementations there. They never get trigger and actually crash saying: 'Delegate must respond to locationManager:didUpdateLocations:'
. If I move the same didUpdateLocations
and didFailWithError
code to ViewController
, everything works as expected.
Is there something I'm missing on why this is not working through protocol extensions? The class is recognized as comforming to CLLocationManagerDelegate
, otherwise it would fail at locationManager.delegate = self
. Any ideas on how to make this work or is there a bug somewhere?
protocol extension is pure Swift staff. The rules for dispatch for protocol extensions are:
IF the inferred type of a variable is the protocol
IF the inferred type of the variable is the type THEN the type’s implementation is called.
Taking all this in account ...
other option is to do something like ...
if all types are known at compile time and there is no 'optional' method in protocol, it works 'as expected'
for further reading see this and this