Objective-C Design Patterns – Success/Failure Blocks vs Completion Block

design-patternsobjective c

I see two common patterns for blocks in Objective-C. One is a pair of success:/failure: blocks, the other is a single completion: block.

For example, lets say I have a task that will return an object asynchronously and that task might fail. The first pattern is -taskWithSuccess:(void (^)(id object))success failure:(void (^)(NSError *error))failure. The second pattern is -taskWithCompletion:(void (^)(id object, NSError *error))completion.

success:/failure:

[target taskWithSuccess:^(id object) {
    // W00t! I've got my object
} failure:^(NSError *error) {
    // Oh noes! report the failure.
}];

completion:

[target taskWithCompletion:^(id object, NSError *error) {
    if (object) {
        // W00t! I've got my object
    } else {
        // Oh noes! report the failure.
    }
}];

Which is the preferred pattern? What are the strengths and weaknesses? When would you use one over the other?

Best Answer

Completion callback (opposed to success/failure pair) is more generic. If you need to prepare some context before dealing with return status, you can do it just before "if (object)" clause. In success/failure case you have to duplicate this code. This depends on callback semantics, of course.

Related Topic