SwiftUI ListView调用.onDelete更新Firestore后未正常更新问题
问题分析
你的列表在删除操作后消失,核心原因是手动修改数组和Firestore快照监听器的自动更新产生了冲突:
- 你在
onDelete中手动移除了ownFlights的元素; - 同时
removeUserFromFlight修改了Firestore文档,触发快照监听器重新执行fetchListedFlights; - 此时该Flight的
ConList已不含用户ID,会被compactMap过滤,导致ownFlights被重新赋值为不包含该Flight的数组; - 手动删除+快照自动更新的双重操作,会导致SwiftUI的列表状态混乱,最终出现列表消失的异常。
另外,重复调用fetchListedFlights会添加多个快照监听器,加剧状态更新的冲突问题。
解决方案
1. 移除手动删除数组元素的代码
不需要在onDelete中手动操作ownFlights,快照监听器会在Firestore文档更新后自动重新过滤并更新数组:
.onDelete { indexSet in if let index = indexSet.first { let flight = flightViewModel.ownFlights[index] flightViewModel.removeUserFromFlight(flight: flight, userID: Auth.auth().currentUser?.uid ?? "") // 删掉这行手动删除代码:flightViewModel.ownFlights.remove(at: index) } }
2. 确保ViewModel的ownFlights是@Published属性
确认你的FlightsViewModel中ownFlights的定义正确,保证SwiftUI能监听其变化:
class FlightsViewModel: ObservableObject { @Published var ownFlights: [Flight] = [] // 其他属性和方法... }
3. 确认Flight结构体符合Identifiable
保证ForEach能正确识别列表元素,避免因为ID问题导致的渲染异常:
struct Flight: Identifiable { let id: String let flightNumber: String let depDate: String let conList: [String] let numCons: Int // 其他属性... }
4. 避免重复添加快照监听器
fetchListedFlights中的addSnapshotListener会注册一个持续监听的监听器,不要在onDelete中重复调用该方法,否则会产生多个监听器,导致多次重复更新数组。
原理说明
Firestore的addSnapshotListener会在文档发生任何变化时自动触发回调,重新生成符合过滤条件的ownFlights数组。当你调用removeUserFromFlight修改文档后,快照监听器会立即感知到变化,重新执行过滤逻辑,自动将不再包含用户ID的Flight从ownFlights中移除,SwiftUI会根据@Published的更新自动刷新列表,完全不需要手动操作数组。
内容的提问来源于stack exchange,提问作者stygarfield
相关产品推荐
相关产品推荐

