Declarar um parâmetro de método de bloco sem usar um typedef

146

É possível especificar um parâmetro de bloco de método no Objective-C sem usar um typedef? Deve ser, como ponteiros de função, mas não consigo acessar a sintaxe vencedora sem usar um typedef intermediário:

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

somente as compilações acima, todas estas falham:

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

e não me lembro de outras combinações que tentei.

Bogatyr
fonte

Respostas:

238
- ( void )myMethodTakingPredicate: ( BOOL ( ^ )( int ) )predicate
Macmade
fonte
9
+1, embora a typedefdeva realmente ser preferida para casos mais complicados.
Fred Foo
3
- ( void )myMethodTakingPredicate: ( BOOL ( ^ )( NSString *name, NSString *age ) )predicate { //How Should I Access name & age here...? }
Mohammad Abdurraafay
6
Esses são apenas nomes de parâmetros. Apenas use-os.
Macmade
1
@larsmans Eu concordo, a menos que esse predicado / bloco específico seja usado em muitos lugares onde seria mais claro tê-lo digitado. A Apple definiu uma série de blocos bastante simples, mas o fez de forma que foi fácil encontrar o que eles queriam na documentação.
mtmurdock
2
Forte recomendação! Nomeie suas variáveis. Eles serão preenchidos automaticamente em código utilizável. Então substitua BOOL ( ^ )( int )por BOOL ( ^ )( int count ).
funroll
65

É assim que acontece, por exemplo ...

[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
fonte
Existe um motivo para você não usar o método [NSString isEqualToString:]?
orkoden
2
Nada específico. Eu apenas uso muito para 'comparar:'. '[NSString isEqualToString:]' é uma maneira melhor.
Mohammad Abdurraafay
Você precisa da palavra responsena smartBlocksdefinição do método? Você não poderia apenas dizer (NSString*))handler {?
Ash
Você pode ter (NSString *)) handler. Isso também é válido.
Mohammad Abdurraafay
9

Outro exemplo (esse problema se beneficia de vários):

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

Ainda mais 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
fonte