使用addSnapshotListener异步获取Firebase数据元素数量问题求解
问题修复方案
根因说明
- ViewModel 中定义的监听方法全程没有被调用,Firestore 的数据监听逻辑从未执行,无法拉取到远端数据
- Firestore 的
addSnapshotListener是异步回调方法,你在onAppear中同步读取数组长度时,网络请求还没返回,拿到的永远是初始值 0 - 额外定义的
@State var count没有和 ViewModel 中的@Published属性绑定,就算后续数组数据更新,count 也不会同步刷新视图
修复后的代码
ViewModel.swift
import Foundation import SwiftUI import Firebase class ViewModel: ObservableObject { // @Published 标记的属性变更时会自动通知关联视图刷新 @Published var array = [Any]() func addSnapshotListener() { Firestore.firestore().collection("Posts").addSnapshotListener { [weak self] snap, err in guard let self = self, let docs = snap, err == nil else { return } // 每次获取新快照先清空旧数据,避免后续文档变更时重复累加 self.array.removeAll() docs.documentChanges.forEach { doc in self.array.append(doc) } } } }
CheckArrayCount.swift
import SwiftUI struct CheckArrayCount: View { @StateObject var viewModel = ViewModel() var body: some View { VStack{ // 直接读取 @Published 属性的长度,数据更新时会自动刷新 Text 展示 Text("arrayCount:\(viewModel.array.count)") } .onAppear { // 触发Firestore监听调用,之前的代码遗漏了这一步 viewModel.addSnapshotListener() } } }
额外注意事项
- 闭包中使用
[weak self]是为了避免循环引用,防止 ViewModel 无法正常释放造成内存泄漏 - 每次拿到新快照先清空原有数组,是为了避免后续文档新增/修改/删除触发回调时,重复累加相同的文档数据
- 不需要额外定义中间变量 count 存储数组长度,直接读取 @Published 修饰的数组属性的长度即可,视图会自动跟随属性变更刷新
内容的提问来源于stack exchange,提问作者Tio
相关产品推荐
相关产品推荐

