Im using Coordinator pattern and therefore setting window.rootViewController
I need to perform some async operations.
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
var coordinator : MainCoordinator!
//I have added the async to scene func
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) async {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: UIScreen.main.bounds)
window?.windowScene = windowScene
coordinator = MainCoordinator(window: window!)
await coordinator.start()
MainCoordinator call for setting rootVC
lazy var rootViewController: UIViewController = UIViewController()
lazy var tabCoordinator: TabCoordinator = TabCoordinator(tabBarController: rootViewController as! UITabBarController)
func start() async {
if UserDefaults.standard.bool(forKey: "Logged") {
await showTabVC()
} else {
showLoginVC()
}
}
func showTabVC() async {
rootViewController = tabBarController
tabCoordinator = TabCoordinator(tabBarController: rootViewController as! UITabBarController)
let tabVC = await tabCoordinator.start()
window.rootViewController = tabVC
window.makeKeyAndVisible()
}
As the TabCoordinator class has start method that returns UIViewController it is marked with @MainActor
so the UI can update as well after finishing with start method.
With code structured like this after running it I end up with black screen and I don't know why?
I have managed to make it work if I change the scene
method from scene delegate by removing the async
from scene method and placing coordinator.start inside Task{}
everything works well:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: UIScreen.main.bounds)
window?.windowScene = windowScene
coordinator = MainCoordinator(window: window!)
Task{
await coordinator.start()
}
What is the problem that async
cause to scene method as I consider this as just another way that is less pleasant to read?
Adding async
to a method changes its type signature.
func scene(
_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions
) async {
and
func scene(
_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions
) {
are two different methods.
The UIWindowSceneDelegate
protocol requires the synchronous method, so adding async
to it means that the method isn't matching the protocol requirement anymore, hence it won't be called by the system.
You don't get a compiler error for this due to the fact that the method is an optional protocol requirement, so not implementing it doesn't actually break the protocol conformance.