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

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

最佳答案

您可以将整个循环放在一个 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/

相关文章:

ios - 使用 STTwitter 更改用户关注/取消关注

iphone - 将文本文件保存到 iOS 7 中的文档目录

variables - 未检测到 UITextField 更改?

ios - Phonegap 只有 1 个 buttonIndex 在 Notification.confirm 中工作

IOS上传图片到AWS 3 生成随机唯一键名

ios - 从不同的 View 更改 View textLabel

ios - subview Controller View 不适合 parent 在 iPhone X 上的 View

ios - swift 中 WKInterfaceController openParentApplication 的替代方案

ios - UIScrollView 可以滚动,但不能从用户交互中滚动

ios - 为什么 Xcode 6.3 beta 调试器会显示 Swift NSData 的字节数为 190 但没有属性?