【问题标题】:Class Observable object @Published variable always empty类 Observable 对象 @Published 变量始终为空
【发布时间】:2020-09-14 13:49:06
【问题描述】:

我正在尝试从 firebase firestore 获取集合。下面是我的 ViewModel 我无法将数据存储在 @Published var 类别对象中。我无法找到确切的问题,我对 swift 有点陌生,但前一段时间完全相同的事情正在工作,我做错了什么吗?

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()
        }
    }
}

【问题讨论】:

  • 这是因为您正在对数据库进行异步调用,因此在返回数据之前执行打印。由于categories 已发布,因此您不必担心这一点,因此当数组获取值时,任何观察者都会收到通知。
  • 谢谢我错过了它是异步的事实,但正如大卫在答案中解释的那样,问题不在于@Published,而在于@observed 对象,因为我在视图本身中创建它。

标签: swift firebase google-cloud-firestore swiftui


【解决方案1】:

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

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

UI 问题来自您在视图中创建 @ ObservedObject 属性这一事实。这是完全不正确的,因为每当 View@ObservedObject 属性更新时,视图将被重绘,这将导致其属性也被重新计算。您可以通过在视图的 init 中注入您的视图模型来解决此问题。查看this answer 以获取有关如何将@ObservedObjects 注入Views 的更详细说明。

【讨论】:

  • 嘿感谢您的回答,即使在主视图中将其初始化为 - `MainView - @State var formViewModel = FormViewModel() CategoriesView(viewModel: self.formViewModel) ` CategoriesView - `@ObserverdObject var viewmodel: FormViewModel `
  • @RahulBajaj 你试过调试你的代码吗? categories 是否实际更新并包含元素?如果在CategoriesViewbody 中下断点,在categories 更新后会被命中吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-04
  • 1970-01-01
  • 2021-05-05
  • 1970-01-01
  • 2019-05-27
相关资源
最近更新 更多