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


146

Чи можна вказати параметр блоку методу в Objective-C без використання typedef? Це повинно бути, як функціональні вказівники, але я не можу потрапити на виграшний синтаксис без використання проміжного типуdef:

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

лише вищезгадані компіляції, всі ці помилки:

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

і я не можу згадати, які інші комбінації я пробував.


Відповіді:


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

9
+1, хоча 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
}];

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));
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.