简体   繁体   English

SwiftUI 和 Firestore - 启动时从不同 collections 读取多个文档的逻辑

[英]SwiftUI and Firestore - logic for reading multiple documents from different collections at startup

I'm using Firebase Firestore in my SwiftUI app project.我在我的 SwiftUI 应用程序项目中使用 Firebase Firestore。 At the start of the app, I want to read multiple documents from various collections.在应用程序启动时,我想从各种 collections 读取多个文档。

Let's say I have collection A (1 document), B (2 documents) and C (4 documents).假设我有集合 A(1 个文档)、B(2 个文档)和 C(4 个文档)。 The data in the documents from A and B determine which documents from C I have to read. A 和 B 的文档中的数据决定了我必须阅读 C 中的哪些文档。

Currently, I have a DatabaseHelper class which has a readCollection function for each collection (each of these readCollection functions call readDocument functions to create a listener for each required document).目前,我有一个 DatabaseHelper class,每个集合都有一个 readCollection function(这些 readCollection 函数中的每一个都调用 readDocument 函数来为每个必需的文档创建一个侦听器)。 Each readCollection function as well as each readDocument function has a completion handler.每个 readCollection function 以及每个 readDocument function 都有一个完成处理程序。 At the start of the app, I start with reading collection A. After completing the read, it then starts reading B, and so on:在应用程序启动时,我从阅读集合 A 开始。阅读完成后,它会开始阅读 B,依此类推:

func listen(completion: @escaping () -> ()) {
  readA() {
    readB() {
      readC() {
        completion()
      }
    }
  }
}

My app is waiting for the listen function to complete before displaying any data.在显示任何数据之前,我的应用正在等待 listen function 完成。

This approach is 'kind of working', HOWEVER, it does not seem to be the optimal approach.这种方法“有点工作”,但是,它似乎不是最佳方法。 For example, if I read A, then I read both documents from B, the completion handler from B is called twice, which results in two calls for readC(), unless I count the document reads for B and only call the completion after the last read.例如,如果我读取 A,然后我从 B 读取两个文档,B 的完成处理程序被调用两次,这导致两次调用 readC(),除非我计算 B 的文档读取并且只在上次阅读。 THEN, the problem is, that only an update to the second document in B triggers the completion handler and reloads documents from C, but not an update to the first document in B.那么,问题是,只有更新 B 中的第二个文档才会触发完成处理程序并从 C 重新加载文档,但不会更新 B 中的第一个文档。

Surely, there has to be a better logic to load my data from the database at the start of my app, which handles each document update during runtime correctly and without unneccessary double-reads.当然,必须有一个更好的逻辑来在我的应用程序启动时从数据库加载我的数据,它在运行时正确处理每个文档更新并且没有不必要的重复读取。

Does anyone have a better approach?有没有人有更好的方法? Thanks谢谢

So here is a possible solution.所以这是一个可能的解决方案。 You'll have to modify it to your needs but as you provided little to no code for your issue it has to do.您必须根据需要修改它,但由于您几乎没有为您的问题提供任何代码,所以它必须这样做。

  1. Get your data from A从 A 获取数据
  2. When that data arrives use it to determine what data to get from B. Use a completion handler for that.当该数据到达时,使用它来确定要从 B 获取哪些数据。为此使用完成处理程序。 Other solutions could be and are not limited to (Dispatcher etc.).其他解决方案可以但不限于(Dispatcher 等)。
  3. Determine what data to get from C with the data provided from B. Same procedure as in Nr.2 to wait for it.用B提供的数据确定从C得到什么数据。和Nr.2一样的过程等待它。

This is just a basic representation of a potential procedure of your problem.这只是您问题的潜在过程的基本表示。 It is oversimplified but should help you understand:它过于简单化,但应该可以帮助您理解:

class DatabaseHelper: ObservableObject {
    
    @Published var myDataA: Array<String> = []
    @Published var myDataB: Array<String> = []
    @Published var myDataC: Array<String> = []
    
    init() {
        self.getData(dataBaseACollectionName: "dataBase_A")
    }
    
    // Get A Data
    private func getData(dataBaseACollectionName: String) {
        self.dataBaseCollectionGetDocuments(collectionName: dataBaseACollectionName) { isSucceededA in
            if !isSucceededA.isEmpty {
                self.myDataA = isSucceededA
                
                // Get first "documentID from A to determine what in B I have to read
                self.getSpecificDocumentFromDataBase(collectionName: self.myDataA.first ?? "randomCollection", documentID: self.myDataA.first ?? "randomDocument") { isSucceededB in
                    if !isSucceededB.isEmpty {
                        self.myDataB = isSucceededB
                        
                        // Get first "documentID from B to determine what in C I have to read
                        self.getSpecificDocumentFromDataBase(collectionName: self.myDataB.first ?? "randomCollection", documentID: self.myDataB.first ?? "randomDocument") { isSucceededC in
                            if !isSucceededC.isEmpty {
                                self.myDataC = isSucceededC
                                // done
                            }
                        } // C
                        
                    }
                } // B
                
            } // A
        }
    }
    
    // I made just one wrapper function for the DB call as all myData Arrays are from the same type (containing Strings)
    private func dataBaseCollectionGetDocuments(collectionName: String ,completing: @escaping (Array<String>) -> Void) {
        
        if !collectionName.isEmpty {
            var dataArray: Array<String> = []
            let group = DispatchGroup()
            group.enter() // initial enter
            
            Firestore.firestore().collection(collectionName).getDocuments() { (documents, error) in
                if error != nil {
                    print("Error getting amount of recipes in last seen")
                } else {
                    for doc in documents!.documents {
                        group.enter()
                        dataArray.append(doc.documentID) // Just appending ID as it is a String
                        group.leave()
                    }
                }
                group.leave() // Initial leave
            }
            
            group.notify(queue: DispatchQueue.global(qos: .background)) {
                completing(dataArray)
            }
        }
        
    }
    
    // For Specific documents
    private func getSpecificDocumentFromDataBase(collectionName: String, documentID: String ,completing: @escaping (Array<String>) -> Void) {
        
        if !collectionName.isEmpty && !documentID.isEmpty {
            var dataArray: Array<String> = []
            let group = DispatchGroup()
            group.enter() // initial enter
            
            let docRef = Firestore.firestore().collection(collectionName).document(documentID)
            docRef.getDocument() { (document, error) in
                group.enter()
                if error != nil {
                    print("Error getting amount of recipes in last seen")
                } else {
                    dataArray.append(document!.documentID) // Just appending ID as it is a String
                    group.leave()
                }
                group.leave() // Initial leave
            }
            
            group.notify(queue: DispatchQueue.global(qos: .background)) {
                completing(dataArray)
            }
        }
        
    }
    
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从 Firestore 中的多个子集合的多个子集合中获取所有文档的最有效方法是什么? - What is the most efficient way to get all documents from multiple sub-collections of multiple sub-collections in Firestore? 使用 SwiftUI 在 Firestore 中匹配 collections - Matching collections in Firestore using SwiftUI 我可以使用 Firestore 检索具有相同名称的不同集合中相同子集合的文档吗? - Can I retrieve documents of same subcollection in different collections with the same name, using Firestore? 无法从 FIRESTORE 的集合中获取多个文档 - UNABLE TO Get multiple documents from a collection FROM FIRESTORE 多个 collections 在 1 个批量写入 firestore - Multiple collections in 1 batched write firestore 我无法从 FireStore 打印多个文档 - I can't print multiple documents from FireStore 我想从 firestore 中的集合中获取多个字段的文档 - I want to get documents for multiple fields from a collection in firestore 如何从 firestore 一次获取多个集合组的文档? - How to get multiple collection group's documents at once from firestore? 读取文档 firestore 的子集合中的文档(V9(模块化)) - Read documents in the sub-collections of a document firestore (V9 (Modular)) 为 RecyclerView 获取多个 Firestore 文档 - Fetching Multiple Firestore Documents for RecyclerView
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM