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

在applicationDidFinishLaunchingWithOptions中基于Firestore数据设置根控制器

解决方案:重启APP时根据Firestore的openOrder值切换根视图控制器

我来帮你梳理下这个问题的核心解决思路——本质是要处理异步数据读取和UI更新的时序问题,因为Firestore的读取是异步操作,不能直接在启动时同步阻塞主线程来等待结果。下面是具体的实现方案和常见坑的规避:

核心步骤拆解

  1. 先确认用户认证状态:要读取用户的订单数据,必须先拿到当前已登录的用户,避免未登录状态下的权限错误。
  2. 异步读取Firestore中的订单数据:用回调或async/await等待读取完成,不要同步阻塞主线程。
  3. 主线程更新根视图控制器:所有UI操作必须在主线程执行,所以拿到openOrder值后要切回主线程设置rootVC。

代码示例(Swift + SceneDelegate,适配iOS 13+)

方式1:用async/await(Swift 5.5+ 推荐)

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = (scene as? UIWindowScene) else { return }
    let window = UIWindow(windowScene: windowScene)
    self.window = window
    
    // 第一步:检查用户是否已登录
    if let currentUser = Auth.auth().currentUser {
        Task {
            do {
                // 第二步:异步读取用户的订单(这里假设订单集合是"orders",用userId关联用户)
                let orderQuery = try await Firestore.firestore()
                    .collection("orders")
                    .whereField("userId", isEqualTo: currentUser.uid)
                    .getDocuments()
                
                // 处理订单数据
                let openOrder: Bool
                if let orderDoc = orderQuery.documents.first {
                    openOrder = orderDoc.data()["openOrder"] as? Bool ?? false
                } else {
                    // 用户无订单时默认设为false,跳转到新建订单页
                    openOrder = false
                }
                
                // 第三步:回到主线程设置根视图控制器
                DispatchQueue.main.async {
                    let rootVC = openOrder ? OpenOrderViewController() : NewOrderViewController()
                    window.rootViewController = UINavigationController(rootViewController: rootVC)
                    window.makeKeyAndVisible()
                }
            } catch {
                // 读取失败的容错处理(比如网络问题)
                print("读取订单失败:\(error.localizedDescription)")
                DispatchQueue.main.async {
                    window.rootViewController = UINavigationController(rootViewController: NewOrderViewController())
                    window.makeKeyAndVisible()
                }
            }
        }
    } else {
        // 用户未登录,跳转到登录页
        window.rootViewController = UINavigationController(rootViewController: LoginViewController())
        window.makeKeyAndVisible()
    }
}

方式2:用完成回调(兼容旧版Swift)

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = (scene as? UIWindowScene) else { return }
    let window = UIWindow(windowScene: windowScene)
    self.window = window
    
    guard let currentUser = Auth.auth().currentUser else {
        window.rootViewController = UINavigationController(rootViewController: LoginViewController())
        window.makeKeyAndVisible()
        return
    }
    
    // 异步读取订单数据
    Firestore.firestore()
        .collection("orders")
        .whereField("userId", isEqualTo: currentUser.uid)
        .getDocuments { [weak self] querySnapshot, error in
            guard let self = self else { return }
            // 必须回到主线程更新UI
            DispatchQueue.main.async {
                if let error = error {
                    print("读取订单出错:\(error)")
                    window.rootViewController = UINavigationController(rootViewController: NewOrderViewController())
                    window.makeKeyAndVisible()
                    return
                }
                
                let openOrder = querySnapshot?.documents.first?.data()["openOrder"] as? Bool ?? false
                let rootVC = openOrder ? OpenOrderViewController() : NewOrderViewController()
                window.rootViewController = UINavigationController(rootViewController: rootVC)
                window.makeKeyAndVisible()
            }
        }
}

常见坑点提醒

  • 必须在主线程更新UI:Firestore的回调默认在后台线程,直接设置rootVC会导致崩溃,一定要用DispatchQueue.main.async包裹。
  • 默认值处理:如果订单中openOrder字段不存在,要给一个默认值(比如false),避免强制解包崩溃。
  • 错误容错:网络异常、权限不足都可能导致读取失败,一定要处理error情况,给用户一个兜底页面。
  • 订单查询逻辑:如果用户可能有多个订单,要根据你的业务调整查询条件(比如只查最新的订单,或者特定状态的订单)。

内容的提问来源于stack exchange,提问作者H.Epstein

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:11:27