当另外两个完成块被调用时,调用完成块 [英] Call completion block when two other completion blocks have been called

查看:88
本文介绍了当另外两个完成块被调用时,调用完成块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数doEverything,它带有一个完成块.它调用另外两个函数doAlphadoBeta,它们都具有完成块.这两个功能应该异步运行.我想在其他两个函数都调用它们的完成块之后调用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)
}

doAlphadoBeta应该同时运行,一旦它们都完成,则应使用alpha和beta的结果调用完成块.

我已经阅读了调度组和障碍,但是我不确定哪个是最合适的,它们如何引入新的作用域(关于我正在使用的两个变量)以及应该如何实现./p>

非常感谢.

解决方案

Grand Central Dispatch(GCD)是您在此处尝试执行的操作的不错选择,您可以使用

或者,您可以通过这种方式实现它(我发现它更具可读性):

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆