如何将Swift新增的Async/Await特性与Firestore监听器结合使用
用Swift async/await重写Firestore快照监听器实现
你可以直接使用Firebase Firestore内置的异步序列API完成重写,无需手动封装续体,重写后完整代码如下:
// 重写后返回异步 throwing 序列,支持持续接收快照更新 func listen(for user: User) -> AsyncThrowingStream<CurrentUser, Error> { AsyncThrowingStream { continuation in // 和原逻辑保持参数一致添加快照监听器 let listener = db.collection("Users") .document(user.uid) .addSnapshotListener(includeMetadataChanges: true) { document, error in if let error = error { continuation.yield(with: .failure(.networkError)) // 若为不可恢复错误可自行调用continuation.finish()终止序列 return } guard let document = document else { continuation.yield(with: .failure(.operationFailure)) return } do { guard let profile = try document.data(as: Profile.self, with: .estimate) else { continuation.yield(with: .failure(.operationFailure)) return } continuation.yield(.success(CurrentUser(user, profile: profile))) } catch { continuation.yield(with: .failure(.operationFailure)) } } // 监听序列终止事件,自动移除监听器避免内存泄漏 continuation.onTermination = { @Sendable _ in listener.remove() } } }
调用方式
需要在异步上下文中使用for try await遍历异步序列接收实时更新:
Task { do { for try await currentUser in listen(for: 已登录用户实例) { // 每次用户数据更新都会触发此处逻辑 print("最新用户数据: \(currentUser)") } } catch { print("监听出错: \(error)") } }
核心说明
- 监听器属于持续推送更新的流式场景,因此不使用单次async方法,而是以
AsyncThrowingStream作为返回值,符合实时监听的特性 - 内置序列终止时的监听器自动移除逻辑,避免忘记调用
remove()导致的内存泄漏 - 所有错误处理、参数配置、解码逻辑完全和原回调版本保持一致,无逻辑差异
内容的提问来源于stack exchange,提问作者otymartin
相关产品推荐
相关产品推荐

