0

How would you perform N asynchronous operations, such as network calls, working with completion block operations and no delegates/notifications?

Given N methods like this:

- (void)methodNWithCompletion:(void (^)(Result *))completion {
    Operation *operation = [Operation new];

    // ...
    // Asynchronous operation performed here
    // ...

    return;
}

A straightforward solution would be to call each operation in the completion block of the previous one:

[self method1WithCompletion:^(Result *result) {
    // ...
    [self method2WithCompletion:^(Result *result) {
        // ...
        [self method3WithCompletion:^(Result *result) {
            // ...
            [self method4WithCompletion:^(Result *result) {
                NSLog(@"All done");
            }
        }
    }
}

but I'm looking for a more elegant and reusable solution, easier to write and maintain (with no many indented blocks).

Many thanks, DAN

1
  • 1
    If the question is "how do I know when they're done", you'd generally use dispatch_group. So, enter the group before doing each asynchronous call, exit the group in the completion handler of the asynchronous call, and then configure a dispatch_group_notify to be performed when all of the asynchronous calls are done. E.g., stackoverflow.com/a/29716069/1271826 or stackoverflow.com/a/34532865/1271826. Commented Oct 30, 2016 at 21:13

1 Answer 1

3

It all depends on what you want to do. Many powerful sophisticated tools are at your disposal. You can use such things as:

  • Serial queue (if you want the completion blocks run in order)

  • Concurrent queue (if you don't care whether the completion blocks execute simultaneously or in what order)

  • Dispatch group (if there is something you want to do only after all completion blocks have finished)

  • Operation and OperationQueue (if you want to establish the dependency order in which networking operations must take place - see esp. the fantastic WWDC 2015 video on this topic)

Sign up to request clarification or add additional context in comments.

9 Comments

I need the completion blocks to be executed in a given order and some code to be executed after all of them have ended. I was trying to write a solution with no Operation/OperationQueue in order to keep the code quite simple.
Then, reading what I said in my answer, you would use a serial queue and a dispatch group. In my opinion Operation is more expressive and can handle the unexpected more gracefully, but you can manage without it if you are using completion blocks and not delegate methods.
Yes, I'll definitely have a look at that approach, thank you!
@DAN - "I need the completion blocks to be executed in a given order..." - Are you sure? Do you absolutely need to use the results of one in order to start the subsequent one? You pay a huge performance penalty for requiring them to be executed in a particular order. If you have to, so be it, but then that suggests broader design problems.
This has been asked and answered many times, so I'm not inclined to post another answer on this topic. My point is that Dan asked "I have a bunch of asychronous methods with completion handlers" and I just wanted to make sure that he knew that he can't just add those to a serial queue and expect that to work. I'd suggest operations or promises/futures. Or just do something simple like only initiating one request in the completion handler of the prior one.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.