SwiftUI中Firestore的add回调与快照监听器是否可能引发竞态条件?
问题解答
预判正确性
你的判断完全正确,该场景确实存在竞态风险,最终会出现书籍重复的问题。
实际执行逻辑
Firestore 的所有回调默认都会派发到主队列串行执行,因此标记(1)和(2)的代码不会真的同时运行,但二者的执行顺序完全由系统调度决定,没有固定先后:
- 调用
add(_:completion:)写入数据成功后,Firestore 会同时触发两个回调:add方法自带的完成回调、你提前注册的快照监听器回调 - 两个回调都会被提交到主队列的待执行任务队列,谁先被调度执行是完全不确定的
你预判的两种情况都会真实发生:
- 若
add的完成回调先执行:先向books追加数据,后续监听器回调直接用服务端返回的完整列表覆盖books属性,不会出现重复 - 若监听器回调先执行:已经把包含新增书籍的完整列表赋值给
books,后续add的完成回调再追加一次相同的书籍,就会出现重复数据
问题修复建议
- 最简方案:直接删除
add方法完成回调里的self.books.append(book)逻辑即可。快照监听器已经会自动同步服务端的最新数据,不需要手动做追加操作。 - 如果要做本地乐观更新提升体验,可以在追加前做去重校验:先判断
books中是否已经存在相同ID的Book实例,不存在再执行追加。 - 另外你现有代码存在逻辑错误:监听器里的
guard error != nil else { completion(.networkError); return }写反了判断条件,应该改为guard error == nil else,否则无错误时反而会返回网络错误。
内容的提问来源于stack exchange,提问作者rayaantaneja
相关产品推荐
相关产品推荐

