Declarar un parámetro de método de bloque sin usar un typedef

146

¿Es posible especificar un parámetro de bloque de método en Objective-C sin usar un typedef? Debe ser, como punteros de función, pero no puedo acertar en la sintaxis ganadora sin usar un typedef intermedio:

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

solo las compilaciones anteriores, todas estas fallan:

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

y no recuerdo qué otras combinaciones he probado.

Bogatyr
fuente

Respuestas:

238
- ( void )myMethodTakingPredicate: ( BOOL ( ^ )( int ) )predicate
Macmade
fuente
9
+1, aunque typedefrealmente debería preferirse a para casos más complicados.
Fred Foo
3
- ( void )myMethodTakingPredicate: ( BOOL ( ^ )( NSString *name, NSString *age ) )predicate { //How Should I Access name & age here...? }
Mohammad Abdurraafay
66
Esos son solo nombres de parámetros. Solo úsalos.
Macmade
1
@larsmans Estoy de acuerdo, a menos que este predicado / bloque en particular se use en muchos lugares donde sería más claro tenerlo definido. Apple ha definido una serie de bloques que eran bastante simples, pero lo hicieron de tal manera que fue fácil encontrar lo que querían en la documentación.
mtmurdock
2
¡Fuerte recomendación! Nombra tus variables. Se autocompletarán en código utilizable. Entonces reemplace BOOL ( ^ )( int )con BOOL ( ^ )( int count ).
funroll
65

Así es como va, por ejemplo ...

[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");
    }
}
Mohammad Abdurraafay
fuente
¿Hay alguna razón por la que no usa el método [NSString isEqualToString:]?
orkoden
2
Nada específico. Solo estoy acostumbrado a usar 'comparar:' mucho. '[NSString isEqualToString:]' es una mejor manera.
Mohammad Abdurraafay
¿Necesita la palabra responseen la smartBlocksdefinición del método? ¿No podrías simplemente decir (NSString*))handler {?
Ash
Es posible que tenga (NSString *)) handler. Eso también es válido.
Mohammad Abdurraafay
9

Otro ejemplo (este problema se beneficia de múltiples):

@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
fuente
2

¡Aún más claro!

[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));
}
Hemang
fuente