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.


Antworten:


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

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");
    }
}

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
}];

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));
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.