Wie funktioniert ein Completion Handler unter iOS?

Ich versuche, Completion Handler & Blöcke zu verstehen. Ich glaube, Sie können Blöcke für viele Deep-Programming-Dinge ohne Completion-Handler verwenden, aber ich glaube, ich verstehe, dass Completion-Handler auf Blöcken basieren. (Grundsätzlich benötigen Completion-Handler also Blöcke, aber nicht umgekehrt.)

Also habe ich diesen Code über das alte Twitter-Framework im Internet gesehen:

[twitterFeed performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
        if (!error) {
            self.successLabel.text = @"Tweeted Successfully";
            [self playTweetSound];
        } else {
            // Show alert
        }
        // Stop indicator 
        sharedApplication.networkActivityIndicatorVisible = NO;
    }];

Hier rufen wir eine Methode auf, die Sachen macht (TWRequest ausführt) und zurückgibt, wenn sie mit responseData & urlResponse & error fertig ist. Erst wenn es zurückkehrt, führt es den Block aus, der gewährt wird, und stoppt den Aktivitätsindikator. PERFEKT!

Dies ist ein Setup, das ich für eine andere App habe, die funktioniert, aber ich versuche, die Teile zusammenzufügen:

@interface
Define an ivar
typedef void (^Handler)(NSArray *users);
Declare the method
+(void)fetchUsersWithCompletionHandler:(Handler)handler;

@implementation
+(void)fetchUsersWithCompletionHandler:(Handler)handler {
    //...Code to create NSURLRequest omitted...
    __block NSArray *usersArray = [[NSArray alloc] init];

    //A. Executes the request 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

        // Peform the request
        NSURLResponse *response;
        NSError *error = nil;
        NSData *receivedData = [NSURLConnection sendSynchronousRequest:request
                                                     returningResponse:&response
                                                                 error:&error];
        // Deal with your error
        if (error) {
            }
            NSLog(@"Error %@", error);
            return;
        }
        // Else deal with data
        NSString *responseString = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
        usersArray = [NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSASCIIStringEncoding] options:0 error:nil];

        // Checks for handler & returns usersArray to main thread - but where does handler come from & how does it know to wait tip usersArray is populated?
        if (handler){
            dispatch_sync(dispatch_get_main_queue(), ^{
            handler(usersArray);
            });
        }
    });
}

Hier ist mein Verständnis:

fetchUsersWithCompletionHandler ist offensichtlich das Homolog von performRequestWithHandlerLeider ist dies etwas komplexer, da ein GCD-Aufruf im Weg ist ...

Grundsätzlich wird jedoch die Anforderung ausgeführt und der Fehler behandelt, die Daten werden behandelt und dann wird der Handler überprüft. Meine Frage ist, wie funktioniert dieses Handlerteil? Ich verstehe, wenn es existiert, wird es an die Hauptwarteschlange zurücksenden und das usersArray zurücksenden. Aber woher weiß es, dass es warten muss, bis usersArray gefüllt ist? Ich denke, was mich verwirrt, ist die Tatsache, dass der method: block in diesem Fall einen weiteren Block enthält, den dispatch_async-Aufruf. Ich vermute, was ich suche, ist die Logik, die tatsächlich Sachen macht und weiß, wann die responseData und urlResponse zurückgegeben werden sollen. Ich weiß, es ist nicht die gleiche App, aber ich kann den Code für performRequestWithHandler nicht sehen.

Antworten auf die Frage(1)

Ihre Antwort auf die Frage