iOS16下Swift/SwiftUI使用Firebase获取数据延迟显示求助
iOS 16 SwiftUI + Firebase 数据加载延迟问题修复
核心问题分析
iOS 16 对 SwiftUI 视图更新机制、线程安全的要求更严格,结合你的代码,问题集中在后台线程更新UI数据、ObservableObject 属性未正确标记以及视图刷新触发时机这几个关键点上。
修复步骤
1. 主线程更新 Firebase 数据
Firebase 的 addSnapshotListener 回调默认在后台线程执行,直接更新数据可能导致 iOS 16 下视图无法及时感知变化。修改 QueryOrder 函数,将数据更新逻辑切换到主线程:
func QueryOrder() { guard let uid = Auth.auth().currentUser?.uid else { return } let query = dataBase.collection("Users").whereField("uid", isEqualTo: uid) query.addSnapshotListener { [weak self] snapshot, error in guard let self = self, let documents = snapshot?.documents else { print("no document or self deallocated") return } // 切换到主线程更新数据 DispatchQueue.main.async { self.orders = documents.map { doc -> Order_placed in let data = doc.data() return Order_placed( customer_name: data["customer_name"] as? String ?? "", total: data["total"] as? Double ?? 0, store_name: data["store_name"] as? String ?? "", customer_address: data["customer_address"] as? String ?? "", customer_phone_number: data["customer_phone_number"] as? Int ?? 0, customer_unit_type: data["customer_unit_type"] as? String ?? "", code_for_delivery: data["code_for_delivery"] as? String ?? "", order_id: data["order_id"] as? String ?? "", status: data["order_status"] as? String ?? "" ) } } } }
2. 标记 orders 为 @Published
确保 FirebaseViewModel 中的 orders 属性用 @Published 修饰,这样 SwiftUI 才能监听数据变化并刷新视图:
class FirebaseViewModel: ObservableObject { @Published var orders: [Order_placed] = [] // ... 其他属性和方法 }
3. 优化视图刷新逻辑
iOS 16 中 onAppear 调用时机提前,可能导致数据更新后视图未重新渲染。可以通过以下方式优化:
- 避免重复添加快照监听,仅在数据为空时触发查询;
- 给
LazyVGrid添加id绑定,强制数据变化时刷新网格。
修改视图代码:
ScrollView { LazyVGrid(columns: items, spacing: 10) { ForEach(StoreFirebase.orders) { item in currentOrdersViewModel(item: item, showCard: $showCard, orderID: $orderID) } } // 绑定订单数量,数据变化时强制刷新网格 .id(StoreFirebase.orders.count) // ... 导航栏按钮代码 } .onAppear() { // 仅在订单为空时触发查询,避免重复添加监听 if StoreFirebase.orders.isEmpty { StoreFirebase.QueryOrder() } }
4. 确保 Order_placed 实现 Identifiable
ForEach 需要数据实现 Identifiable 来正确追踪元素变化,检查 Order_placed 结构:
// 方案1:用UUID生成唯一ID struct Order_placed: Identifiable { let id = UUID() // ... 其他属性(customer_name、total等) } // 方案2:用order_id作为唯一标识(推荐,更贴合业务) struct Order_placed: Identifiable { var id: String { order_id } let order_id: String // ... 其他属性 }
额外排查点
- 检查 Firebase 数据库权限配置,确保当前用户有权限读取
Users集合; - 查看 Xcode 控制台日志,确认是否有 Firebase 权限错误或数据解析错误;
- 临时替换
LazyVGrid为普通VStack测试,排除懒加载组件的刷新问题。
内容的提问来源于stack exchange,提问作者ValentinW
相关产品推荐
相关产品推荐

