【问题标题】:Swift Completion Handler For Loop to be performed once instead of 10 times due to the loop由于循环,Swift Completion Handler For Loop 将执行一次而不是 10 次
【发布时间】:2020-07-24 16:16:06
【问题描述】:

我有一个循环,其中包含一个重复 10 次的 firestore 查询。在所有 10 个查询完成后,我需要调用 (completion: block);在这里,我有我的代码,以便它执行(完成:块)每个查询,但这对服务器和用户的手机来说太重了。我如何在下面进行更改以完成我刚才描述的内容?

static func getSearchedProducts(fetchingNumberToStart: Int, sortedProducts: [Int : [String : Int]], handler: @escaping (_ products: [Product], _ lastFetchedNumber: Int?) -> Void) {

        var lastFetchedNumber:Int = 0
        var searchedProducts:[Product] = []

        let db = Firestore.firestore()

        let block : FIRQuerySnapshotBlock = ({ (snap, error) in

            guard error == nil, let snapshot = snap else {
                debugPrint(error?.localizedDescription)
                return
            }

            var products = snapshot.documents.map { Product(data: $0.data()) }

            if !UserService.current.isGuest {

                db.collection(DatabaseRef.Users).document(Auth.auth().currentUser?.uid ?? "").collection(DatabaseRef.Cart).getDocuments { (cartSnapshot, error) in
                    guard error == nil, let cartSnapshot = cartSnapshot else {
                        return
                    }

                    cartSnapshot.documents.forEach { document in
                        var product = Product(data: document.data())
                        guard let index = products.firstIndex(of: product) else { return }
                        let cartCount: Int = document.exists ? document.get(DatabaseRef.cartCount) as? Int ?? 0 : 0
                        product.cartCount = cartCount
                        products[index] = product
                    }
                    handler(products, lastFetchedNumber)
                }
            }

            else {
                handler(products, lastFetchedNumber)
            }
        })

        if lastFetchedNumber == fetchingNumberToStart {

            for _ in 0 ..< 10 {

                //change the fetching number each time in the loop
                lastFetchedNumber = lastFetchedNumber + 1

                let productId = sortedProducts[lastFetchedNumber]?.keys.first ?? ""

                if productId != "" {
                    db.collection(DatabaseRef.products).whereField(DatabaseRef.id, isEqualTo: productId).getDocuments(completion: block)
                }
            }
        }

    }

正如你在最后看到的那样,由于for _ in 0 ..&lt; 10,我为此查询循环了 10 次:

if productId != "" {
                    db.collection(DatabaseRef.products).whereField(DatabaseRef.id, isEqualTo: productId).getDocuments(completion: block)
                }

所以我需要让 completion: block 处理程序只被调用一次,而不是在这里调用 10 次。

【问题讨论】:

    标签: swift loops for-loop google-cloud-firestore completionhandler


    【解决方案1】:

    使用DispatchGroup。您可以在每次调用异步代码时进入调度组,然后在每次完成时离开。然后当一切都完成后,它会调用通知块,你可以调用你的处理程序。下面是一个简单的示例:

    let dispatchGroup = DispatchGroup()
    let array = []
    
    for i in array {
        dispatchGroup.enter()
        somethingAsync() {
            dispatchGroup.leave()
        }
    }
    
    dispatchGroup.notify(queue: .main) {
        handler()
    }
    

    【讨论】:

    • 解释得好!!
    猜你喜欢
    • 2017-03-13
    • 2016-11-09
    • 1970-01-01
    • 1970-01-01
    • 2021-10-17
    • 2016-11-22
    • 1970-01-01
    • 2023-02-22
    • 2019-06-20
    相关资源
    最近更新 更多