ok, so I have 2 answers and 1 question @AntonL
Answer #1 from an Apple Engineer:
locationManagerDidChangeAuthorization isn’t guaranteed to be called on the MainActor. CoreLocation documentation says that:
Core Location calls the methods of your delegate object using the RunLoop of the thread on which you initialized the CLLocationManager object.
But even if you create the CLLocationManager instance on the main thread, Swift Concurrency system can’t know that at compile time.In this case the method needs to be nonisolated and, if necessary, should start up a task and await a call to a helper method like this:
@MainActor
class MyClass: NSObject, CLLocationManagerDelegate {
var authorizationStatus: CLAuthorizationStatus?
nonisolated func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
let newStatus = manager.authorizationStatus
Task { await self.changeAuthorizationStatus(to: newStatus) }
}
func changeAuthorizationStatus(to status: CLAuthorizationStatus) {
self.authorizationStatus = status
}
}
You can pass a CLAuthorizationStatus between actors without generating a warning, because CLAuthorizationStatus is Sendable.
Answer #2: My iteration on my previous post:
Manager is not Sendable in my case. But the authorizarionStatus is. So we could write this to please the compiler:
nonisolated func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
let newStatus = manager.authorizationStatus
DispatchQueue.main.async {
self.authorizationStatus = status
}
}
The question: @eskimo
Will my second solution with dispatching to main queue somehow affect the performance?
I find it more readable and more "locally reasoned" than the first one with a helper method.
Topic:
UI Frameworks
SubTopic:
AppKit
Tags: