Zadeklaruj parametr metody bloku bez użycia typu typedef

146

Czy można określić parametr bloku metody w Objective-C bez użycia typedef? Musi być, podobnie jak wskaźniki do funkcji, ale nie mogę trafić w składnię wygrywającą bez użycia pośredniej czcionki:

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

kompiluje się tylko powyższe, wszystkie te zawodzą:

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

i nie pamiętam, jakich innych kombinacji próbowałem.

Bogatyr
źródło

Odpowiedzi:

238
- ( void )myMethodTakingPredicate: ( BOOL ( ^ )( int ) )predicate
Macmade
źródło
9
+1, chociaż typedefnaprawdę powinno być preferowane w bardziej skomplikowanych przypadkach.
Fred Foo
3
- ( void )myMethodTakingPredicate: ( BOOL ( ^ )( NSString *name, NSString *age ) )predicate { //How Should I Access name & age here...? }
Mohammad Abdurraafay
6
To tylko nazwy parametrów. Po prostu ich używaj.
Macmade
1
@larsmans Zgadzam się, chyba że ten konkretny predykat / blok jest używany w wielu miejscach, w których byłoby bardziej oczywiste, aby je zdefiniować. Firma Apple zdefiniowała szereg bloków, które były dość proste, ale zrobiło to tak, że łatwo było znaleźć to, czego chcieli w dokumentacji.
mtmurdock
2
Mocna rekomendacja! Nazwij swoje zmienne. Będą automatycznie uzupełniane do użytecznego kodu. Więc zastąpić BOOL ( ^ )( int )z BOOL ( ^ )( int count ).
funroll
65

Tak to jest, na przykład ...

[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
źródło
Czy jest jakiś powód, dla którego nie używasz metody [NSString isEqualToString:]?
orkoden
2
Nic konkretnego. Po prostu używam często „porównaj”. Jednak „[NSString isEqualToString:]” jest lepszym sposobem.
Mohammad Abdurraafay
Czy potrzebujesz słowa responsew smartBlocksdefinicji metody? Nie mógłbyś po prostu powiedzieć (NSString*))handler {?
Ash
Możesz mieć (NSString *)) handler. To też jest ważne.
Mohammad Abdurraafay,
9

Inny przykład (ten problem korzysta z wielu):

@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
źródło
2

Jeszcze wyraźniej!

[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
źródło