使用DispatchGroup,DispatchQueue和DispatchSemaphore按顺序执行带有for循环的Swift 4异步调用 [英] Swift 4 async call with for loop execute in order using DispatchGroup, DispatchQueue and DispatchSemaphore

查看:388
本文介绍了使用DispatchGroup,DispatchQueue和DispatchSemaphore按顺序执行带有for循环的Swift 4异步调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想按顺序快速运行for循环,DispatchGroup会将它们一起触发,因此我想使用DispatchQueue和DispatchSemaphore来实现我的目标.我无法使程序正常运行,如何强制他们等待并逐一运行?

I want to run a for loop in swift in order, DispatchGroup will fire them together, so I want to use DispatchQueue and DispatchSemaphore to achieve my goal. I failed to make my program work, how can I force them to wait and run one by one?

let dispatchGroup = DispatchGroup()
let dispatchQueue = DispatchQueue(label: "taskQueue")
let dispatchSemaphore = DispatchSemaphore(value: 1)

for c in self.categories {

    dispatchSemaphore.wait()

    dispatchQueue.async(group: dispatchGroup) {

        if let id = c.categoryId {

            dispatchGroup.enter()

            self.downloadProductsByCategory(categoryId: id) { success, data in

                if success, let products = data {

                    self.products.append(products)
                }

                dispatchSemaphore.signal()
                dispatchGroup.leave()
            }
        }
    }
}

dispatchGroup.notify(queue: dispatchQueue) {

    self.refreshOrderTable { _ in

        self.productCollectionView.reloadData()

        NVActivityIndicatorPresenter.sharedInstance.stopAnimating()
    }
}


感谢宫廷,这是我的最终代码:


Thanks to Palle, here is my final code:

let dispatchGroup = DispatchGroup()
let dispatchQueue = DispatchQueue(label: "taskQueue")
let dispatchSemaphore = DispatchSemaphore(value: 0)

dispatchQueue.async {

    for c in self.categories {

        if let id = c.categoryId {

            dispatchGroup.enter()

            self.downloadProductsByCategory(categoryId: id) { success, data in

                if success, let products = data {

                    self.products.append(products)
                }

                dispatchSemaphore.signal()
                dispatchGroup.leave()
            }

            dispatchSemaphore.wait()
        }
    }
}

dispatchGroup.notify(queue: dispatchQueue) {

    DispatchQueue.main.async {

        self.refreshOrderTable { _ in

            self.productCollectionView.reloadData()
        }
    }
}

推荐答案

您可以将整个循环放在一个块中,而不仅仅是将下载功能放在一个块中:

You can put the whole loop in a block instead of putting just the download function in a block:

dispatchQueue.async {
    for c in self.categories {
        if let id = c.categoryId {
            self.downloadProductsByCategory(categoryId: id) { success, data in
                if success, let products = data {
                    self.products.append(products)
                }

                dispatchSemaphore.signal()
            }
            dispatchSemaphore.wait()
        }
    }
}


您可以使用compactMap解开产品ID来简化代码:


You can simplify your code by using compactMap to unwrap your product ids:

for id in self.categories.compactMap({$0.categoryId}) { ... }

这篇关于使用DispatchGroup,DispatchQueue和DispatchSemaphore按顺序执行带有for循环的Swift 4异步调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆