Firestore查询未完成即执行后续代码,求解决方案
解决Firestore查询完成后再执行后续代码的问题
问题根源分析
你之前的尝试失效,核心原因如下:
- Async/Await版本:虽然函数标记了
async,但内部仍使用Firestore的闭包版getDocuments,没有真正等待异步操作完成,函数会立即返回。 - 完成处理程序版本:将
completion(true)放在了for循环内部,每遍历一个文档就触发一次完成回调,而非所有数据处理完毕后统一触发;且后续依赖数据的代码未放在回调闭包内,导致提前执行。 - 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
相关产品推荐
相关产品推荐

