iOS中Firebase Firestore的set与update操作失效问题求助
问题分析与修复方案
核心问题
- 冗余的快照监听器嵌套
每次调用emitSingleTripLocation都会给tripRef新增快照监听器,导致:
- 大量重复监听器堆积,占用资源
- 监听器回调异步执行,3秒一次的定时器会触发多个未完成的更新请求,逻辑混乱
- 监听器回调内再执行
setData属于冗余操作,完全不需要先监听快照再更新
空requestId的隐性问题
requestId默认值为空字符串,若LocalDB.shared.currentTripDetail?.acceptedRequestId为nil,你会尝试更新ID为空的无效文档,Firestore不会报错,但数据不会写入到目标位置。异步操作与定时器的冲突
3秒一次的定时器会频繁触发更新,而Firestore写入是异步的,前一次请求未完成时新请求可能被中断或覆盖,导致数据未同步。
修复后代码
var singleTripLocationTimer: Timer? // 保留定时器初始化逻辑,注意在页面销毁或停止更新时调用singleTripLocationTimer?.invalidate() if singleTripLocationTimer == nil { singleTripLocationTimer = Timer.scheduledTimer(withTimeInterval: 3, repeats: true, block: { (timer) in if MySocketManager.shared.currentEmitType == .singleTripLocation { self.emitSingleTripLocation() } }) } private func emitSingleTripLocation() { guard let currentLocation = AppLocationManager.shared.locationManager.location else { print("当前位置为空,跳过更新") return } guard let authId = LocalDB.shared.driverDetails?.id else { print("司机ID为空,跳过更新") return } guard let requestId = LocalDB.shared.currentTripDetail?.acceptedRequestId, !requestId.isEmpty else { print("请求ID为空,跳过更新") return } let heading = AppLocationManager.shared.currentHeading?.trueHeading ?? currentLocation.course var jsonObject = [String:Any]() jsonObject["lat"] = currentLocation.coordinate.latitude jsonObject["lng"] = currentLocation.coordinate.longitude jsonObject["success"] = true var distArr = [[String: Any]]() jsonObject["distancee"] = self.getDistanceFrom(distArr) print("准备更新数据", jsonObject) // 直接执行文档更新,移除冗余的快照监听逻辑 self.requestRef.document(requestId).setData(jsonObject, merge: true) { error in if let error = error { print("更新行程数据失败: \(error)") return } // 单独处理司机状态更新 var additionalData = [String: Any]() additionalData["is_available"] = false self.ref.document(authId).updateData(additionalData) { error in if let error = error { print("更新司机状态失败: \(error)") } } } }
额外优化建议
- 定时器清理:在页面销毁或停止位置更新时,必须调用
singleTripLocationTimer?.invalidate(),避免定时器持续运行消耗资源。 - 位置防抖:可以记录上次更新的坐标,只有当位置偏移超过阈值时才触发更新,减少无意义的重复请求。
- 错误排查:每个
guard分支添加打印日志,快速定位哪一步导致更新终止。
内容的提问来源于stack exchange,提问作者Shreedharshan Msd
相关产品推荐
相关产品推荐

