The following Swift UIKit code produces the warning "Cannot access property 'authController' with a non-sendable type 'AuthController' from non-isolated deinit; this is an error in Swift 6":
import UIKit
class AuthFormNavC: UINavigationController {
let authController: AuthController
init(authController: AuthController) {
self.authController = authController
super.init(rootViewController: ConsentVC())
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
authController.signInAnonymouslyIfNecessary()
}
}
Swift 5.10, Xcode 15.3 with complete strict concurrency checking.
What is the workaround?
Please don't ask me why I'm doing what I'm doing or anything unrelated to the question.
If you're wondering why I want to call authController.signInAnonymouslyIfNecessary()
when the navigation controller is denitialized, my goal is to call it when the navigation controller is dismissed (or popped), and I think that the deinitializer of a view controller is the only method that is called if and only if the view controller is being dismissed (or popped) in my case. I tried observing variables like isViewLoaded
in the past using KVO but I couldn't get it to work passing any combination of options in observe(_:options:changeHandler:)
.
In a nutshell: call signInAnonymouslyIfNecessary()
in viewDidDisappear()
: avoid in general dealing with class deinitializers.
But if you insist on calling signInAnonymouslyIfNecessary()
in the deinitializer, you can:
- Mark AuthController as @MainActor
- Mark signInAnonymouslyIfNecessary as nonisolated
- Wrap signInAnonymouslyIfNecessary in a Task:
@MainActor final class AuthController {
nonisolated func signInAnonymouslyIfNecessary() {
Task { @MainActor in
/// ...
}
}
}