Firestore多子集合获取保养记录 添加新记录后出现重复问题
解决Firestore获取保养记录时的重复数据问题
问题根源
- 使用
addSnapshotListener时,每次数据更新(包括新增、修改记录)都会触发回调,原代码每次触发都直接将当前车辆的所有保养记录追加到expenseItems数组中,旧数据未被清理,导致重复累积。 - 循环处理多辆车时,每辆车的监听器独立触发,每次触发都往同一个
expenseItems里追加数据,进一步加剧重复问题。 - 遇到无ID的车辆时直接
return,会导致后续车辆的记录无法被获取。
修复方案
- 新增字典存储单辆车的保养记录,避免不同车辆的记录混乱。
- 每次监听器触发时,更新对应车辆的记录到字典中,再将字典中所有记录扁平合并为完整列表,替换
expenseItems而非追加。 - 将无ID车辆的
return改为continue,确保后续车辆正常处理。
修改后的代码
import Foundation import FirebaseFirestore import FirebaseFirestoreSwift class ExpensesManager: ObservableObject { // 用字典存储各车辆的保养记录,key为车辆ID private var vehicleExpenses: [String: [MaintenanceItem]] = [:] @Published private(set) var expenseItems: [MaintenanceItem] = [] let db = Firestore.firestore() init(vehicles: [Vehicle]) { fetchExpenseItems(vehicles: vehicles) print("ExpensesManager init func succeess!") } func fetchExpenseItems(vehicles: [Vehicle]) { for vehicle in vehicles { guard let vehicleID = vehicle.id else { print("VehicleID is not found, skip this vehicle") continue // 改为continue,不终止后续车辆处理 } db.collection("Vehicles").document(vehicleID).collection("MaintenanceItems") .addSnapshotListener { [weak self] querySnapshot, error in guard let self = self else { return } guard let documents = querySnapshot?.documents else { print("Error fetching documents: \(String(describing: error))") return } // 解析当前车辆的保养记录 let newExpenses = documents.compactMap { document -> MaintenanceItem? in do { return try document.data(as: MaintenanceItem.self) } catch { print("Error decoding document into Expense: \(error)") return nil } } // 更新字典中对应车辆的记录 self.vehicleExpenses[vehicleID] = newExpenses // 扁平合并所有车辆的记录,生成完整列表 self.expenseItems = self.vehicleExpenses.values.flatMap { $0 } print("Expenses array updated, total items: \(self.expenseItems.count)") } } } }
关键改动说明
vehicleExpenses字典:单独存储每辆车的保养记录,避免不同车辆的数据互相干扰。- 替换而非追加:每次监听器触发时,先更新对应车辆的记录,再重新合并生成完整的
expenseItems,彻底解决重复问题。 continue替代return:确保即使某辆车无ID,后续车辆的记录仍能正常获取。[weak self]避免循环引用:在闭包中使用弱引用,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Ilia Krasnobaev
相关产品推荐
相关产品推荐

