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.


Respuestas:


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

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");
    }
}

¿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
}];

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));
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.