Google cloud firestore SwiftUI列表闪烁“我的数据”,然后使用ObserveObject显示空列表以获取Firestore数据
下面是一个场景:Onappear我的视图调用ObserveObject类的getData方法。在调试期间,我看到它检索数据并按预期返回数组。当我的视图出现在模拟器上时,数据在列表上短暂闪烁,然后列表变为空白。我在我的应用程序中的几个地方使用了相同的模式,在某些情况下它可以工作(列表显示为它应该的样子),而在其他情况下它变为空白 我正在13.0和13.3模拟器上进行测试,因为在其中一个模拟器上存在各种swiftUI错误。我认为这可能是因为对Firestore的异步调用,但我已经实现了完成处理程序。如果我将ObservedObject更改为@状态,则列表将正确显示,但添加新项时不会刷新 下面是一个不起作用的示例的代码: 我的看法是:Google cloud firestore SwiftUI列表闪烁“我的数据”,然后使用ObserveObject显示空列表以获取Firestore数据,google-cloud-firestore,swiftui,swiftui-list,Google Cloud Firestore,Swiftui,Swiftui List,下面是一个场景:Onappear我的视图调用ObserveObject类的getData方法。在调试期间,我看到它检索数据并按预期返回数组。当我的视图出现在模拟器上时,数据在列表上短暂闪烁,然后列表变为空白。我在我的应用程序中的几个地方使用了相同的模式,在某些情况下它可以工作(列表显示为它应该的样子),而在其他情况下它变为空白 我正在13.0和13.3模拟器上进行测试,因为在其中一个模拟器上存在各种swiftUI错误。我认为这可能是因为对Firestore的异步调用,但我已经实现了完成处理程序。
import SwiftUI
import Firebase
struct ManagerListView: View {
var circuitId: String
@State private var isMgr:Bool = true //TODO: reset to false
@EnvironmentObject var session : SessionStore
@ObservedObject var managerArray = ManagerList()
func deleteMgrDb(manager: Manager) {
let docRef = Firestore.firestore().collection("circuits").document(circuitId).collection("managers").document(manager.id)
docRef.delete { (error) in
if error != nil {
print(error!.localizedDescription)
}
}
}
var body: some View {
List {
ForEach(managerArray.managers) { i in
Text("\(i.firstName) \(i.lastName) \(i.phone)").deleteDisabled(!self.isMgr)
}.onDelete { (indexset) in
let manager = self.managerArray.managers[indexset.first!]
print("Here \(self.managerArray.managers[indexset.first!])")
//TODO: Check if owner (can't remove owner) or maybe if at least one manager (then delete owner?)
self.managerArray.managers.remove(atOffsets: indexset)
self.deleteMgrDb(manager: manager)
}.disabled(!isMgr)
}.onAppear(perform: {
self.managerArray.getData(forcircuitid: self.circuitId) { (error) in
if error != nil {
//TODO: Return data error to user
print(error!.localizedDescription)
}
//TODO: isMgr
}
}).onDisappear(perform: {
self.managerArray.stopMgrListListener()
}).navigationBarItems(trailing: isMgr ?
NavigationLink(destination: CircuitManagerAddView(circuitId: self.circuitId, currentmgrs: managerArray.managers), label: {
Image(systemName: "plus")
}): nil) //.disabled(!isMgr))
}
}
我的可观察类:
class ManagerList: ObservableObject {
@Published var managers = [Manager]()
var listener: ListenerRegistration?
func getData(forcircuitid: String, completion: @escaping (Error?)->Void) {
let db = Firestore.firestore().collection("circuits").document(forcircuitid).collection("managers")
self.managers.removeAll()
listener = db.addSnapshotListener { (snapshot, error) in
if error != nil {
print(error!.localizedDescription)
completion(error)
}
else {
for i in snapshot!.documentChanges {
if i.type == .added {
let email = i.document.get("email") as! String
let lastName = i.document.get("lastname") as! String
let firstName = i.document.get("firstname") as! String
let phone = i.document.get("phonenum") as! String
let manager = Manager(id: email, lastName: lastName, firstName: firstName, phone: phone)
self.managers.append(manager)
//TODO: Changed
}
}
completion(nil)
}
}
}
对于正在工作的列表,除了更改Firestore文档、数据元素、变量名等之外,我使用的代码基本上完全相同。。它们甚至在调试器中以相同的方式运行,唯一的区别是一些工作和显示列表,而另一些不显示 列表项正在消失,因为每当您的
ManagerList
数据更改时,都会重新初始化ManagerListView
。发生这种情况时,ManagerList
也会重新初始化,但是只有在视图第一次出现时才会调用您在onAppear
中执行的代码,而不会在随后的数据更改时调用
SwiftUI不保证@ObservedObject
变量的生存期。你必须自己处理。在iOS 14中,他们引入了@StateObject
,使之更容易实现。你可以读更多
作为旁注,
onDisappear
仅在视图不再显示时调用。最好将ManagerList
中的Firebase侦听器从classes de initialiser函数中删除。我们也看到了同样的问题。有人有解决办法吗?你已经解决了这个问题吗?