Объявите параметр метода блока без использования typedef

146

Можно ли указать параметр блока метода в Objective-C без использования typedef? Должно быть, как указатели на функции, но я не могу использовать синтаксис победы без использования промежуточного определения типа:

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

только вышеупомянутые компиляции, все они терпят неудачу:

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

и я не могу вспомнить, какие еще комбинации я пробовал.

Богатырь
источник
3
goshdarnblocksyntax.com
Кайл Клегг

Ответы:

238
- ( void )myMethodTakingPredicate: ( BOOL ( ^ )( int ) )predicate
Macmade
источник
9
+1, хотя a typedefдействительно должно быть предпочтительным для более сложных случаев.
Фред Фу
3
- ( void )myMethodTakingPredicate: ( BOOL ( ^ )( NSString *name, NSString *age ) )predicate { //How Should I Access name & age here...? }
Мухаммед Абдурраафай
6
Это просто имена параметров. Просто используйте их.
Macmade
1
@ larsmans Я согласен, если только этот конкретный предикат / блок не используется во многих местах, где было бы более понятно иметь его typedef'd. Apple определила ряд блоков, которые были довольно простыми, но сделали так, чтобы было легко найти то, что они хотели в документации.
mtmurdock
2
Сильная рекомендация! Назовите свои переменные. Они будут автоматически заполнены в пригодный для использования код. Так что замените BOOL ( ^ )( int )на BOOL ( ^ )( int count ).
funroll
65

Вот как это происходит, например ...

[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");
    }
}
Мухаммед Абдурраафай
источник
Есть ли причина, по которой вы не используете метод [NSString isEqualToString:]?
orkoden
2
Ничего конкретного. Я просто использую, чтобы использовать 'сравнить:' много. «[NSString isEqualToString:]» - лучший способ.
Мухаммед Абдурраафай
Вам нужно слово responseв smartBlocksопределении метода? Не могли бы вы просто сказать (NSString*))handler {?
Эш
Вы можете иметь (NSString *)) handler. Это также верно.
Мухаммед Абдурраафай
9

Другой пример (эта проблема выигрывает от нескольких):

@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
источник
2

Еще понятнее!

[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
источник