79

I have just discovered completion blocks:

 completion:^(BOOL finished){


                     }];

What do I need to do to have my own method take a completion block?

jscs
  • 63,694
  • 13
  • 151
  • 195
user2206906
  • 1,310
  • 2
  • 13
  • 18

3 Answers3

234

1) Define your own completion block,

typedef void(^myCompletion)(BOOL);

2) Create a method which takes your completion block as a parameter,

-(void) myMethod:(myCompletion) compblock{
    //do stuff
    compblock(YES);
}

3)This is how you use it,

[self myMethod:^(BOOL finished) {
    if(finished){
        NSLog(@"success");
    }
}];

enter image description here

Thilina Chamath Hewagama
  • 9,039
  • 3
  • 32
  • 45
  • compclock(YES) is the same as return compclock = YES ? – user2206906 May 01 '13 at 18:52
  • Yes, You got it, we can put compclock(YES)/compclock(NO) depending on the requirement, we can return NO for failure completions here – Thilina Chamath Hewagama May 01 '13 at 18:55
  • track the returned value: if(finished) NSLog(@"success");else NSLog(@"failure"); – Thilina Chamath Hewagama May 01 '13 at 18:58
  • 2
    If you're a C/C++ programmer, then I find it very easy to remember the syntax of block declaration using a pointer to function syntax. The only thing you need to do is replace "*" in C/C++ function-pointer with "^" ...thought it might help someone in future :) – Viren Mar 18 '14 at 04:20
  • For more than one parameter in the block, use a comma to separate. E.g. `completion:(void (^)(BOOL success, NSString* videoPath))` – Stan James Oct 27 '14 at 21:36
  • What if my method is prepareForSegue ?!?! any possible way to use it for that? Like if user wants to go to the next page and I need to show waiting animation once the prepareForSegue starts preparing and do compBlock(YES) inside prepareForSegue method? – Reza.Ab Feb 16 '18 at 23:48
25

You define the block as a custom type:

typedef void (^ButtonCompletionBlock)(int buttonIndex);

Then use it as an argument to a method:

+ (SomeButtonView*)buttonViewWithTitle:(NSString *)title 
                          cancelAction:(ButtonCompletionBlock)cancelBlock
                      completionAction:(ButtonCompletionBlock)completionBlock

When calling this in code it is just like any other block:

[SomeButtonView buttonViewWithTitle:@"Title"
                       cancelAction:^(int buttonIndex) {
                             NSLog(@"User cancelled");
                   } 
                     completionAction:^(int buttonIndex) {
                             NSLog(@"User tapped index %i", buttonIndex);
                   }];

If it comes time to trigger the block, simply call completionBlock() (where completionBlock is the name of your local copy of the block).

jszumski
  • 7,430
  • 11
  • 40
  • 53
2

Block variables are similar in syntax to function pointers in C.

Because the syntax is ugly they are often typedefed, however they can also be declared normally.

typedef void (^MyFunc)(BOOL finished);

- (void)myMethod:(MyFunc)func
{
}

See this answer for non typedef:

Declare a block method parameter without using a typedef

Community
  • 1
  • 1
Justin Meiners
  • 10,754
  • 6
  • 50
  • 92