I have the following code:
/* @MainActor */ class Locator : NSObject, ObservableObject
{
private let locationManager: CLLocationManager
private var authorizationContinuation: CheckedContinuation<CLAuthorizationStatus, Never>?
@Published var authorizationStatus: CLAuthorizationStatus
@Published var location: CLLocation?
@Published var error: Error?
override init()
{
locationManager = CLLocationManager()
authorizationStatus = locationManager.authorizationStatus
super.init()
locationManager.delegate = self
}
/* @MainActor */ func checkAuthorizationStatus() async -> CLAuthorizationStatus
{
let status = locationManager.authorizationStatus
if status == .notDetermined
{
return await withCheckedContinuation
{ continuation in
authorizationContinuation = continuation
locationManager.requestWhenInUseAuthorization()
}
}
else
{
authorizationStatus = status <=== WARNING
return status
}
}
}
extension Locator : CLLocationManagerDelegate
{
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager)
{
authorizationStatus = manager.authorizationStatus
authorizationContinuation?.resume(returning: authorizationStatus)
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error)
{
print(error)
self.error = error
location = nil
}
}
Without either making the whole class or checkAuthorizationStatus()
@MainActor
, I get the following run-time warning:
Publishing changes from background threads is not allowed; make sure to publish values from the main thread (via operators like receive(on:))
What would be your considerations for choosing to make the whole class @MainActor
or just the function/'part' that needs it, in this case and in general?
EDIT: To satisfy people that vote to close this questions because it's seems based on opinion: Is there in the above code any run-time difference between the two options?
UI needs to be updated on the MainActor
or you get the “publishing changes in the background warning”. If the purpose of the class
is to update UI it should be wrapped with MainActor
.