You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 10:40:37