使用DispatchGroup,DispatchQueue和DispatchSemaphore按顺序执行带有for循环的Swift 4异步调用 [英] Swift 4 async call with for loop execute in order using DispatchGroup, DispatchQueue and DispatchSemaphore
问题描述
我想按顺序快速运行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屋!