148

Is it possible to specify a method block parameter in Objective-C without using a typedef? It must be, like function pointers, but I can't hit on the winning syntax without using an intermediate typedef:

typedef BOOL (^PredicateBlock_t)(int);
- (void) myMethodTakingPredicate:(PredicateBlock_t)predicate

only the above compiles, all these fail:

-  (void) myMethodTakingPredicate:( BOOL(^block)(int) ) predicate
-  (void) myMethodTakingPredicate:BOOL (^predicate)(int)

and I can't remember what other combinations I've tried.

Bogatyr
  • 19,255
  • 7
  • 59
  • 72

5 Answers5

240
- ( void )myMethodTakingPredicate: ( BOOL ( ^ )( int ) )predicate
Macmade
  • 52,708
  • 13
  • 106
  • 123
  • 9
    +1, though a `typedef` should really be preferred for more complicated cases. – Fred Foo Mar 30 '11 at 13:35
  • 3
    `- ( void )myMethodTakingPredicate: ( BOOL ( ^ )( NSString *name, NSString *age ) )predicate { //How Should I Access name & age here...? }` – Mohammad Abdurraafay Sep 12 '11 at 08:01
  • 6
    Those are just parameter names. Just use them. – Macmade Sep 12 '11 at 08:48
  • 1
    @larsmans I agree, unless this particular predicate/block is used in a lot of places where it would be more clear to have it typedef'd. Apple has defined a number of blocks that were quite simple, but did so such that it was easy to find what they wanted in documentation. – mtmurdock Feb 29 '12 at 03:23
  • 1
    and how to pass a block to that function. – user4951 Nov 15 '12 at 18:14
  • 1
    Ugh. There is nothing intuitive about this syntax at all. :( – devios1 Feb 26 '14 at 01:30
  • @chaiguy It is if you know how to deal with function pointers. It's the same syntax, with ^ instead of * – Macmade Feb 26 '14 at 08:14
  • @Macmade That's the syntax I'm complaining about. Not criticizing your answer mind you; already +1'd. – devios1 Feb 26 '14 at 21:48
  • 3
    Strong recommendation! Name your variables. They will autocomplete into usable code. So replace `BOOL ( ^ )( int )` with `BOOL ( ^ )( int count )`. – funroll Sep 08 '14 at 19:48
67

This is how it goes, for example...

[self smartBlocks:@"Pen" youSmart:^(NSString *response) {
        NSLog(@"Response:%@", response);
    }];


- (void)smartBlocks:(NSString *)yo youSmart:(void (^) (NSString *response))handler {
    if ([yo compare:@"Pen"] == NSOrderedSame) {
        handler(@"Ink");
    }
    if ([yo compare:@"Pencil"] == NSOrderedSame) {
        handler(@"led");
    }
}
20

http://fuckingblocksyntax.com

As a method parameter:

- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;
funroll
  • 35,925
  • 7
  • 54
  • 59
9

Another example (this issue benefits from multiple):

@implementation CallbackAsyncClass {
void (^_loginCallback) (NSDictionary *response);
}
// …


- (void)loginWithCallback:(void (^) (NSDictionary *response))handler {
    // Do something async / call URL
    _loginCallback = Block_copy(handler);
    // response will come to the following method (how is left to the reader) …
}

- (void)parseLoginResponse {
    // Receive and parse response, then make callback

   _loginCallback(response);
   Block_release(_loginCallback);
   _loginCallback = nil;
}


// this is how we make the call:
[instanceOfCallbackAsyncClass loginWithCallback:^(NSDictionary *response) {
   // respond to result
}];
bshirley
  • 8,217
  • 1
  • 37
  • 43
2

Even more clear !

[self sumOfX:5 withY:6 willGiveYou:^(NSInteger sum) {
    NSLog(@"Sum would be %d", sum);
}];

- (void) sumOfX:(NSInteger)x withY:(NSInteger)y willGiveYou:(void (^) (NSInteger sum)) handler {
    handler((x + y));
}
pkamb
  • 33,281
  • 23
  • 160
  • 191
Hemang
  • 26,840
  • 19
  • 119
  • 186