类 Observable 对象 @Published 变量始终为空
Posted
技术标签:
【中文标题】类 Observable 对象 @Published 变量始终为空【英文标题】:Class Observable object @Published variable always empty 【发布时间】: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
已发布,因此您不必担心这一点,因此当数组获取值时,任何观察者都会收到通知。
programmingios.net/what-asynchronous-means
谢谢我错过了它是异步的事实,但正如大卫在答案中解释的那样,问题不在于@Published,而在于@observed 对象,因为我在视图本身中创建它。
【参考方案1】:
您错过了 addSnapshotListener
是一个异步函数的事实。您的第二次打印不会返回任何数据,因为它会在addSnapshotListener
的异步网络请求返回任何数据之前同步执行。你只能在函数的闭包内访问addSnapshotListener
的异步数据。
但是,您的实际视图未更新的原因与上述不同。您正在从异步闭包内部正确更新 categories
数组,因此每当异步请求完成时,您的 categories
将包含正确的数据。
UI 问题来自您在视图中创建 @ ObservedObject
属性这一事实。这是完全不正确的,因为每当 View
的 @ObservedObject
属性更新时,视图将被重绘,这将导致其属性也被重新计算。您可以通过在视图的 init 中注入您的视图模型来解决此问题。查看this answer 以获取有关如何将@ObservedObject
s 注入View
s 的更详细说明。
【讨论】:
嘿感谢您的回答,即使在主视图中将其初始化为 - `MainView - @State var formViewModel = FormViewModel() CategoriesView(viewModel: self.formViewModel) ` CategoriesView - `@ObserverdObject var viewmodel: FormViewModel ` @RahulBajaj 你试过调试你的代码吗?categories
是否实际更新并包含元素?如果在CategoriesView
的body
中下断点,在categories
更新后会被命中吗?以上是关于类 Observable 对象 @Published 变量始终为空的主要内容,如果未能解决你的问题,请参考以下文章
Java中使用Observer接口和Observable类实践Observer观察者模式
我们什么时候应该使用Observer和Observable?
如何以角度将 JSON 对象数组转换为 Observable 数组
Angular 7 - 对象的 Observables 数组的 Observable 数组