当另外两个完成块被调用时,调用完成块 [英] Call completion block when two other completion blocks have been called
问题描述
我有一个函数doEverything
,它带有一个完成块.它调用另外两个函数doAlpha
和doBeta
,它们都具有完成块.这两个功能应该异步运行.我想在其他两个函数都调用它们的完成块之后调用doEverything
的完成块.
当前,它看起来像这样:
func doEverything(completion: @escaping (success) -> ())) {
var alphaSuccess = false
var betaSuccess = false
doAlpha { success in
alphaSuccess = success
}
doBeta { success in
betaSuccess = success
}
// We need to wait here
completion(alphaSuccess && betaSuccess)
}
doAlpha
和doBeta
应该同时运行,一旦它们都完成,则应使用alpha和beta的结果调用完成块.
我已经阅读了调度组和障碍,但是我不确定哪个是最合适的,它们如何引入新的作用域(关于我正在使用的两个变量)以及应该如何实现./p>
非常感谢.
Grand Central Dispatch(GCD)是您在此处尝试执行的操作的不错选择,您可以使用 DispatchGroup ,如下:
快捷键3:
func doEverything(completion: @escaping () -> ()) {
let queue = DispatchQueue(label: "reverseDomain", attributes: .concurrent, target: .main)
let group = DispatchGroup()
group.enter()
queue.async (group: group) {
print("do alpha")
group.leave()
}
group.enter()
queue.async (group: group) {
print("do beta")
group.leave()
}
group.notify(queue: DispatchQueue.main) {
completion()
}
}
或者,您可以通过这种方式实现它(我发现它更具可读性):
func doEverything(completion: @escaping () -> ()) {
let queue = DispatchQueue(label: "reverseDomain", attributes: .concurrent, target: .main)
let group = DispatchGroup()
queue.async (group: group) {
print("do alpha")
}
queue.async (group: group) {
print("do beta")
}
group.notify(queue: DispatchQueue.main) {
completion()
}
}
请注意,我从completion
闭包中删除了success
标志.
在这种情况下,"do beta"(第二个queue.async
的执行)要等到"do alpha"(第一个queue.async
的执行)完成后才能执行,这是因为queue
目标是.main
.如果要让两个queue.async
同时工作,则无需创建额外的队列,可以通过替换以下内容来由同一队列完成工作:
let queue = DispatchQueue(label: "reverseDomain", attributes: .concurrent, target: .main)
具有:
let queue = DispatchQueue(label: "reverseDomain", attributes: .concurrent)
现在,系统将控制两个queue.async
任务应如何同时工作(很明显,group.notify
将在两个任务完成后执行).
希望这会有所帮助.
I have a function doEverything
that takes a completion block. It calls two other functions, doAlpha
and doBeta
which both have completion blocks. These two functions should run asynchronously. I want to call doEverything
's completion block after both of the other functions have called their completion blocks.
Currently, it looks like this:
func doEverything(completion: @escaping (success) -> ())) {
var alphaSuccess = false
var betaSuccess = false
doAlpha { success in
alphaSuccess = success
}
doBeta { success in
betaSuccess = success
}
// We need to wait here
completion(alphaSuccess && betaSuccess)
}
doAlpha
and doBeta
should run at the same time and, once they've both completed, the completion block should be called with the result of alpha and beta.
I've read into dispatch groups and barriers but I'm not sure which is the most appropriate, how they both introduce new scope (with regards to the two variables I'm using) and how I should implement that.
Many thanks.
Grand Central Dispatch (GCD) is a pretty good choice of what are you trying to do here, you can achieve this by using DispatchQueue and DispatchGroup, as follows:
Swift 3:
func doEverything(completion: @escaping () -> ()) {
let queue = DispatchQueue(label: "reverseDomain", attributes: .concurrent, target: .main)
let group = DispatchGroup()
group.enter()
queue.async (group: group) {
print("do alpha")
group.leave()
}
group.enter()
queue.async (group: group) {
print("do beta")
group.leave()
}
group.notify(queue: DispatchQueue.main) {
completion()
}
}
Or, you can implement it this way (which I find more readable):
func doEverything(completion: @escaping () -> ()) {
let queue = DispatchQueue(label: "reverseDomain", attributes: .concurrent, target: .main)
let group = DispatchGroup()
queue.async (group: group) {
print("do alpha")
}
queue.async (group: group) {
print("do beta")
}
group.notify(queue: DispatchQueue.main) {
completion()
}
}
Note that I removed the success
flag from the completion
closure.
At this case, "do beta" (the execution of the second queue.async
) won't be executed until "do alpha" (the execution of the first queue.async
) finished, and that's because queue
target is .main
. If you want to let both of queue.async
work concurrently, there is no need to create an extra queue, the same queue should does the work, by replacing:
let queue = DispatchQueue(label: "reverseDomain", attributes: .concurrent, target: .main)
with:
let queue = DispatchQueue(label: "reverseDomain", attributes: .concurrent)
Now, the system will control over how both of queue.async
tasks should work concurrently (and obviously, group.notify
will be executed after the tow of the tasks finish).
Hope this helped.
这篇关于当另外两个完成块被调用时,调用完成块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!