Swift中如何根据用户状态切换App启动时的Root ViewController
问题分析与解决方案
核心问题点
你的代码主要存在两个关键问题:
- Window未关联到UIWindowScene:手动创建
UIWindow后,没有将其绑定到传入的scene(即UIWindowScene),导致系统无法正确渲染窗口,引发黑屏。 - Firestore查询异步性未处理:
User.shared.userNameOccupied的赋值依赖Firestore的异步查询,scene(_:willConnectTo:options:)方法执行时,这个布尔值可能还未被正确初始化,导致判断逻辑失效。
修复后的代码实现
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = scene as? UIWindowScene else { return } // 正确初始化Window并关联到WindowScene self.window = UIWindow(windowScene: windowScene) self.window?.frame = UIScreen.main.bounds let storyboard = UIStoryboard(name: "Main", bundle: nil) let welcomeVC = storyboard.instantiateViewController(withIdentifier: "WelcomeViewController") let mainVC = storyboard.instantiateViewController(withIdentifier: "MainViewController") // 先显示临时占位(避免空白屏幕) self.window?.rootViewController = UIViewController() self.window?.makeKeyAndVisible() // 异步检查Firestore中的用户名状态 checkUserNameExistence { [weak self] hasUserName in guard let self = self else { return } // 根据查询结果切换RootViewController self.window?.rootViewController = hasUserName ? mainVC : welcomeVC } } // 封装Firestore查询逻辑(替换你现有检查函数) private func checkUserNameExistence(completion: @escaping (Bool) -> Void) { // 示例:通过当前用户UID查询Firestore用户文档 guard let uid = Auth.auth().currentUser?.uid else { completion(false) return } let db = Firestore.firestore() db.collection("users").document(uid).getDocument { snapshot, error in if let error = error { print("查询失败:\(error.localizedDescription)") completion(false) return } // 判断文档是否存在(即是否已设置用户名) let hasUserName = snapshot?.exists ?? false completion(hasUserName) } }
额外注意事项
- Storyboard标识符验证:确保
WelcomeViewController和MainViewController在Storyboard中的Storyboard ID与代码中使用的标识符完全一致,否则会引发崩溃。 - 内存泄漏防护:使用
[weak self]避免闭包持有导致的内存泄漏。 - 错误处理:在Firestore查询中加入错误处理逻辑,避免因网络问题或权限问题导致流程卡住。
- 加载体验优化:可以自定义一个带加载动画的ViewController作为临时Root,提升用户等待体验。
内容的提问来源于stack exchange,提问作者flolopi
相关产品推荐
相关产品推荐

