Deklarieren Sie einen Blockmethodenparameter ohne typedef

146

Ist es möglich, einen Methodenblockparameter in Objective-C anzugeben, ohne ein typedef zu verwenden? Es muss wie Funktionszeiger sein, aber ich kann die Gewinnsyntax nicht treffen, ohne ein Zwischen-Typedef zu verwenden:

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

nur die oben genannten Kompilierungen, alle diese schlagen fehl:

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

und ich kann mich nicht erinnern, welche anderen Kombinationen ich versucht habe.

Bogatyr
quelle

Antworten:

238
- ( void )myMethodTakingPredicate: ( BOOL ( ^ )( int ) )predicate
Macmade
quelle
9
+1, obwohl a typedeffür kompliziertere Fälle wirklich bevorzugt werden sollte.
Fred Foo
3
- ( void )myMethodTakingPredicate: ( BOOL ( ^ )( NSString *name, NSString *age ) )predicate { //How Should I Access name & age here...? }
Mohammad Abdurraafay
6
Das sind nur Parameternamen. Benutze sie einfach.
Macmade
1
@larsmans Ich stimme zu, es sei denn, dieses bestimmte Prädikat / Block wird an vielen Stellen verwendet, an denen es klarer wäre, es typisiert zu haben. Apple hat eine Reihe von Blöcken definiert, die recht einfach waren, dies jedoch so, dass es einfach war, in der Dokumentation zu finden, was sie wollten.
Mtmurdock
2
Starke Empfehlung! Nennen Sie Ihre Variablen. Sie werden automatisch in verwendbaren Code vervollständigt. Also ersetzen BOOL ( ^ )( int )durch BOOL ( ^ )( int count ).
Funroll
65

So geht es zum Beispiel ...

[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
quelle
Gibt es einen Grund, warum Sie die Methode [NSString isEqualToString:] nicht verwenden?
Orkoden
2
Nichts Spezielles. Ich benutze nur oft 'compare:'. '[NSString isEqualToString:]' ist jedoch ein besserer Weg.
Mohammad Abdurraafay
Benötigen Sie das Wort responsein der smartBlocksMethodendefinition? Könntest du nicht einfach sagen (NSString*))handler {?
Ash
Sie können haben (NSString *)) handler. Das gilt auch.
Mohammad Abdurraafay
9

Ein weiteres Beispiel (dieses Problem profitiert von mehreren):

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

Noch klarer!

[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
quelle