使用DispatchGroup,DispatchQueue和DispatchSemaphore顺序执行带有for循环的Swift 4异步调用

时间:2017-10-21 12:43:22

标签: ios swift

我想在顺序中以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()
        }
    }
}

1 个答案:

答案 0 :(得分:9)

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

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()
        }
    }
}

您可以使用flatMap来展开产品ID来简化代码:

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