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

Firestore查询未完成即执行后续代码,求解决方案

解决Firestore查询完成后再执行后续代码的问题

问题根源分析

你之前的尝试失效,核心原因如下:

  1. Async/Await版本:虽然函数标记了async,但内部仍使用Firestore的闭包版getDocuments,没有真正等待异步操作完成,函数会立即返回。
  2. 完成处理程序版本:将completion(true)放在了for循环内部,每遍历一个文档就触发一次完成回调,而非所有数据处理完毕后统一触发;且后续依赖数据的代码未放在回调闭包内,导致提前执行。
  3. Dispatch Group无效:大概率是enter()和leave()的位置错误,未正确包裹异步查询逻辑。

方案1:正确的Async/Await实现

Firestore从iOS 15+开始支持原生Async/Await API,直接使用该版本即可实现等待:

// 获取用户信息
func getUser() async throws {
    // 使用await等待查询完成
    let querySnapshot = try await self.db.collection("userSetting").getDocuments()
    
    for document in querySnapshot.documents {
        // 用可选绑定替代强制解包,避免崩溃
        guard let userTrust = document.data()["userTrust"] as? String,
              let userGrade = document.data()["userGrade"] as? String,
              let userDisclaimer = document.data()["userDisclaimer"] as? String else {
            print("文档字段缺失或类型不匹配")
            continue
        }
        
        let row = [userTrust, userGrade, userDisclaimer]
        self.userArray.append(row)
        
        // 设置Firebase Analytics用户信息
        self.userTrustInfo = userTrust
        self.userGradeInfo = userGrade
    }
}

调用方式:
后续依赖用户数据的代码必须放在Task内部的await之后,确保数据加载完成后再执行:

internal func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    FirebaseApp.configure()
    db = Firestore.firestore()
    Database.database().isPersistenceEnabled = true

    Task {
        do {
            try await getUser()
            // --------------------------
            // 所有依赖userArray的后续代码写在这里
            // 比如初始化UI、发送Analytics事件等
            print("用户信息加载完成,执行后续逻辑")
            // --------------------------
        } catch {
            print("获取用户信息失败:\(error)")
        }
    }
    
    return true
}

方案2:正确的完成处理程序实现

如果需要兼容iOS 15以下版本,可使用完成回调,但需确保所有数据处理完毕后再触发回调:

func getUser(completion: @escaping (Error?) -> Void) {
    self.db.collection("userSetting").getDocuments() { querySnapshot, err in
        if let err = err {
            print("获取文档错误:\(err)")
            completion(err)
            return
        }
        
        guard let querySnapshot = querySnapshot else {
            let emptyError = NSError(domain: "FirestoreError", code: -1, userInfo: [NSLocalizedDescriptionKey: "查询快照为空"])
            completion(emptyError)
            return
        }
        
        for document in querySnapshot.documents {
            guard let userTrust = document.data()["userTrust"] as? String,
                  let userGrade = document.data()["userGrade"] as? String,
                  let userDisclaimer = document.data()["userDisclaimer"] as? String else {
                print("文档字段异常")
                continue
            }
            
            let row = [userTrust, userGrade, userDisclaimer]
            self.userArray.append(row)
            
            self.userTrustInfo = userTrust
            self.userGradeInfo = userGrade
        }
        
        // 所有文档处理完成后,统一触发完成回调
        completion(nil)
    }
}

调用方式:
依赖数据的后续代码必须放在completion闭包内:

internal func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    FirebaseApp.configure()
    db = Firestore.firestore()
    Database.database().isPersistenceEnabled = true

    getUser { error in
        if let error = error {
            print("加载用户信息失败:\(error)")
            return
        }
        // --------------------------
        // 依赖userArray的后续逻辑写在这里
        print("用户信息加载完成,执行后续代码")
        // --------------------------
    }
    
    return true
}

内容的提问来源于stack exchange,提问作者Nicholas Farmer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 22:07:28