Swift 类可观察对象@已发布变量始终为空

Swift 类可观察对象@已发布变量始终为空,swift,firebase,google-cloud-firestore,swiftui,Swift,Firebase,Google Cloud Firestore,Swiftui,我正在尝试从firebase firestore获取收藏。下面是我的ViewModel,我无法将数据存储在@Published var categories对象中。我找不到确切的问题,我对斯威夫特有点陌生,但前一阵子同样的事情在起作用,我有什么做错了吗 FormViewModel.swift import Firebase import FirebaseFirestore class FormViewModel: ObservableObject { @Published var ca

我正在尝试从firebase firestore获取收藏。下面是我的ViewModel,我无法将数据存储在@Published var categories对象中。我找不到确切的问题,我对斯威夫特有点陌生,但前一阵子同样的事情在起作用,我有什么做错了吗

FormViewModel.swift

import Firebase
import FirebaseFirestore

class FormViewModel: ObservableObject {
    @Published var categories = [Category]()
    private var db = Firestore.firestore()
    
    func fetchCategories() {
        db.collection("companies_by_category").addSnapshotListener { (QuerySnapshot, error) in
            guard let documents = QuerySnapshot?.documents else {
                print("No documents")
                return
            }

            self.categories = documents.compactMap { (QueryDocumentSnapshot) -> Category? in
                return try? QueryDocumentSnapshot.data(as: Category.self)
            }
            print(self.categories) // -> Able to get data
        }
    }
}
我的分类观点

struct CategoriesView: View {
    
    @ObservedObject var viewmodel = FormViewModel()
    
    var body: some View {
        ScrollView {
            List(self.viewmodel.categories) { category in
                ZStack {
                    RoundedRectangle(cornerRadius: 15, style: .continuous)
                        //.foregroundColor(category.selected == true ? Color.yellow.opacity(0.5) : Color.white)
                        .foregroundColor(.white)
                        .shadow(color: Color.black.opacity(0.1), radius: 10, x: 0, y: 0)
                    
                    VStack(spacing: 20) {
                        HStack {
                            Image("\(category.category)")
                                .foregroundColor(Color.gray)
                                .font(.system(size: 20.0))
                            Text(category.category)
                                .font(.system(size: 20.0, weight: .medium))
                                .foregroundColor(Color.black)
                            Spacer()
                        }
                    }
                .padding()
                }
            }
        }
        .onAppear() {
            self.viewmodel.fetchCategories()
        }
    }
}

您缺少一个事实,
addSnapshotListener
是一个异步函数。第二次打印不会返回任何数据,因为它是在
addSnapshotListener
的异步网络请求返回任何数据之前同步执行的。您只能访问函数闭包内的
addSnapshotListener
的异步数据

但是,实际视图未更新的原因与上述不同。您正在从异步闭包内部正确更新
类别
数组,因此每当异步请求完成时,您的
类别
将包含正确的数据


UI问题来自于您在视图中创建了
@ObservedObject
属性这一事实。这是完全错误的,因为每当
视图
@ObservedObject
属性更新时,视图将被重新绘制,这将导致其属性也被重新计算。可以通过在视图的init中注入viewmodel来修复此问题。查看有关如何将
@ObservedObject
s注入
视图
s的更详细说明。

这是因为您正在对数据库进行异步调用,因此在返回数据之前执行打印。您不必担心这一点,因为
categories
已发布,因此当数组获取值时,将通知任何观察者。谢谢,我忽略了它是异步的这一事实,但正如David在回答中解释的,问题不在于@published,但是使用@observed对象,因为我正在视图中创建它。嘿,谢谢你的回答,我的视图在主视图中初始化为-`MainView-@State var formViewModel=formViewModel()CategoriesView(viewModel:self.formViewModel)之后仍然没有显示`CategoriesView-`@ObserverdObject var viewmodel:FormViewModel`@RahulBajaj您试过调试代码吗?
categories
是否实际更新并包含元素?如果在
分类视图
正文
中放置断点,则在更新
分类
后是否会命中断点?