Google cloud firestore SwiftUI列表闪烁“我的数据”,然后使用ObserveObject显示空列表以获取Firestore数据

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的异步调用,但我已经实现了完成处理程序。

下面是一个场景:Onappear我的视图调用ObserveObject类的getData方法。在调试期间,我看到它检索数据并按预期返回数组。当我的视图出现在模拟器上时,数据在列表上短暂闪烁,然后列表变为空白。我在我的应用程序中的几个地方使用了相同的模式,在某些情况下它可以工作(列表显示为它应该的样子),而在其他情况下它变为空白

我正在13.0和13.3模拟器上进行测试,因为在其中一个模拟器上存在各种swiftUI错误。我认为这可能是因为对Firestore的异步调用,但我已经实现了完成处理程序。如果我将ObservedObject更改为@状态,则列表将正确显示,但添加新项时不会刷新

下面是一个不起作用的示例的代码:

我的看法是:

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函数中删除。

我们也看到了同样的问题。有人有解决办法吗?你已经解决了这个问题吗?