这是场景:在我的视图上,我的视图调用了ObservableObject类的getData方法。在调试过程中,我看到它检索数据并按预期返回数组。当我的视图出现在模拟器上时,数据在列表上短暂闪烁,然后列表变为空白。我在应用程序中的多个地方都使用了相同的模式,在某些情况下它可以工作(列表按预期显示),而在其他情况下则为空白。
由于各种swiftUI错误可在一个或另一个上运行,因此我正在13.0和13.3模拟器上进行测试。我认为可能是由于对Firestore的异步调用,但是我实现了完成处理程序。如果我将ObservedObject更改为@State,则该列表会正确显示,但是添加新项目时不会刷新。
以下是其中一个无效示例的代码:
我的观点:
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文档,数据元素,变量名称等外,我基本上使用完全相同的代码。它们甚至在调试器中以相同的方式运行,唯一的区别是工作和显示该列表,其他则没有。
答案 0 :(得分:0)
列表项消失了,因为每次ManagerListView
数据更改时,ManagerList
都会重新初始化。发生这种情况时,ManagerList
也将重新初始化,但是您在onAppear
中执行的代码只会在第一次出现视图时调用,而不会在随后的数据更改时调用。
SwiftUI不保证@ObservedObject
变量的生命周期。您必须自己进行管理。他们在iOS 14中引入了@StateObject
,以简化此过程。您可以阅读更多here。
请注意,onDisappear
仅在不再显示视图时调用。最好从类反初始化函数中删除ManagerList
中的Firebase侦听器。