기존 코드에서는 Task
를 사용하여 비동기적으로 AuthorizationCenter.shared.authorizationStatus
를 가져온 후,
비동기적으로 rootViewController
를 설정하고 DispatchQueue.main.async
에서 UI를 업데이트했다.
하지만 scene(_:willConnectTo:options:)
메서드는 메인 스레드에서 실행돼서,
UI 업데이트를 완전히 안전하게 수행하기 위해 DispatchQueue.main.async
대신 await MainActor.run
을 사용하도록 개선했다.
...
var rootViewController: UIViewController?
Task {
let authorizationsStatus = AuthorizationCenter.shared.authorizationStatus
// 권한 승인 여부 확인
if authorizationsStatus == .approved {
// 권한 설정 되어있을 때, 메인페이지로
rootViewController = MainViewController()
} else {
// 권한 설정 안되어있을 때, 권한 설정 페이지로
rootViewController = PermissionViewController()
}
DispatchQueue.main.async {
guard let rootViewController = rootViewController else { return }
navigationController.setViewControllers([rootViewController], animated: true)
}
}
Task
내부에서 rootViewController
를 설정했기 때문에 비동기 실행으로 인해 nil
상태에서 UI 업데이트가 실행될 가능성이 있음.DispatchQueue.main.async
를 사용했지만, scene(_:willConnectTo:options:)
메서드는 원래 메인 스레드에서 실행되므로 불필요하다고 생각이 들어서 제외했더니 동작을 안함.rootViewController
가 옵셔널(var rootViewController: UIViewController?
)로 선언되어 옵셔널 체크가 필요해짐.func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: scene)
let navigationController = UINavigationController()
self.window = window
window.rootViewController = navigationController
window.makeKeyAndVisible()
Task {
let authorizationsStatus = AuthorizationCenter.shared.authorizationStatus
let rootViewController: UIViewController
// 권한 승인 여부 확인
if authorizationsStatus == .approved {
// 권한 설정 되어있을 때, 메인페이지로
rootViewController = MainViewController()
} else {
// 권한 설정 안되어있을 때, 권한 설정 페이지로
rootViewController = PermissionViewController()
}
await MainActor.run {
navigationController.setViewControllers([rootViewController], animated: true)
}
}
}
await MainActor.run
사용DispatchQueue.main.async
대신 await MainActor.run
을 사용하여 UI 업데이트를 보다 안전하게 실행.Task
내부에서 rootViewController
를 let
으로 선언하여 옵셔널 체크 없이도 안정적으로 값이 설정되도록 보장.Task
내부 코드가 순차적으로 실행됨을 명확히 하기 위해 await
을 사용.navigationController.setViewControllers
를 옵셔널 체크 없이 바로 실행 가능.scene(_:willConnectTo:options:)
는 기본적으로 메인 스레드에서 실행되지만, Task
내부의 코드는 비동기로 실행될 수 있다.DispatchQueue.main.async
보다 await MainActor.run
이 더 적절하다.