使用闭包时如何防止时序问题?
How to prevent Timing Problems When Using Closures?
我正在尝试计算从不同的转义闭包返回的数字之和。在主线程中返回的总和。
import Foundation
var randomTime: Int {
return Int.random(in: 0...1000)
}
func first(completion: @escaping (Int) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(randomTime)) {
completion(1)
}
}
func second(completion: @escaping (Int) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(randomTime)) {
completion(2)
}
}
func third(completion: @escaping (Int) -> Void) {
DispatchQueue(label: "anotherThread").async {
completion(3)
}
}
func fourth(completion: @escaping (Int) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(randomTime)) {
completion(4)
}
}
如果我把你的问题说清楚了,你想对数字求和,但它们的值会在不同的时间出现,具体取决于服务器响应或某种延迟。如果是这种情况,那么您必须使用 DispatchGroup
这是一个辅助函数,它正在调用您的方法 first(completion: @escaping (Int) -> Void)
..... fourth(completion: @escaping (Int) -> Void)
并仅在收到最后一个值时通知主队列。我在代码上添加了一些注释以帮助理解。如果有什么不清楚的地方,请告诉我。
func computeOutPutAfterReceivingAllValues(completion: @escaping(_ sum: Int) -> Void) {
// Make a dispatch group which will notify main queue after making sure that all requests have been proceed.
let computeGroup = DispatchGroup()
var allNumbers: [Int] = []
computeGroup.enter()
first { (firstNumber) in
allNumbers.append(firstNumber)
self.second(completion: { (secondNumber) in
allNumbers.append(secondNumber)
self.third(completion: { (thirdNumber) in
allNumbers.append(thirdNumber)
self.fourth(completion: { (fourthNumber) in
allNumbers.append(fourthNumber)
// IMPORTANT: Leave a group after the last call.
computeGroup.leave()
})
})
})
}
// Notify Main queue and sum all your numbers
computeGroup.notify(queue: .main) {
/// Sum all your numbers in main queue
let sum = allNumbers.reduce(0, +)
completion(sum)
}
}
用法:
您可以在 didLoad 视图中对此进行测试。
override func viewDidLoad() {
super.viewDidLoad()
computeOutPutAfterReceivingAllValues { (sum) in
print("Here is the sum of all numbers: \(sum)")
}
}
// Output on console
Here is the sum of all numbers: 10
我正在尝试计算从不同的转义闭包返回的数字之和。在主线程中返回的总和。
import Foundation
var randomTime: Int {
return Int.random(in: 0...1000)
}
func first(completion: @escaping (Int) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(randomTime)) {
completion(1)
}
}
func second(completion: @escaping (Int) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(randomTime)) {
completion(2)
}
}
func third(completion: @escaping (Int) -> Void) {
DispatchQueue(label: "anotherThread").async {
completion(3)
}
}
func fourth(completion: @escaping (Int) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(randomTime)) {
completion(4)
}
}
如果我把你的问题说清楚了,你想对数字求和,但它们的值会在不同的时间出现,具体取决于服务器响应或某种延迟。如果是这种情况,那么您必须使用 DispatchGroup
这是一个辅助函数,它正在调用您的方法 first(completion: @escaping (Int) -> Void)
..... fourth(completion: @escaping (Int) -> Void)
并仅在收到最后一个值时通知主队列。我在代码上添加了一些注释以帮助理解。如果有什么不清楚的地方,请告诉我。
func computeOutPutAfterReceivingAllValues(completion: @escaping(_ sum: Int) -> Void) {
// Make a dispatch group which will notify main queue after making sure that all requests have been proceed.
let computeGroup = DispatchGroup()
var allNumbers: [Int] = []
computeGroup.enter()
first { (firstNumber) in
allNumbers.append(firstNumber)
self.second(completion: { (secondNumber) in
allNumbers.append(secondNumber)
self.third(completion: { (thirdNumber) in
allNumbers.append(thirdNumber)
self.fourth(completion: { (fourthNumber) in
allNumbers.append(fourthNumber)
// IMPORTANT: Leave a group after the last call.
computeGroup.leave()
})
})
})
}
// Notify Main queue and sum all your numbers
computeGroup.notify(queue: .main) {
/// Sum all your numbers in main queue
let sum = allNumbers.reduce(0, +)
completion(sum)
}
}
用法: 您可以在 didLoad 视图中对此进行测试。
override func viewDidLoad() {
super.viewDidLoad()
computeOutPutAfterReceivingAllValues { (sum) in
print("Here is the sum of all numbers: \(sum)")
}
}
// Output on console
Here is the sum of all numbers: 10