기존 코드에서는 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이 더 적절하다.