我想在 swift 中按顺序运行一个 for 循环,DispatchGroup 会一起触发它们,所以我想使用 DispatchQueue 和 DispatchSemaphore 来实现我的目标。我的程序运行失败,如何强制他们等待并一个一个运行?
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()
}
}
感谢 Palle,这是我的最终代码:
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()
}
}
}
最佳答案
您可以将整个循环放在一个 block 中,而不是只将下载函数放在一个 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 来简化您的代码:
for id in self.categories.compactMap({$0.categoryId}) { ... }
关于ios - 使用 DispatchGroup、DispatchQueue 和 DispatchSemaphore 按顺序执行带有 for 循环的 Swift 4 异步调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46863325/