Ich versuche zu verstehen, Komplettierungshandler & Blöcke. Ich glaube, Sie können Blöcke für viele tiefgreifende Programmieraufgaben ohne Completion-Handler verwenden, aber ich denke, ich verstehe, dass Completion-Handler auf Blöcken basieren. (Im Grunde benötigen die Completion Handler also Blöcke, aber nicht umgekehrt).Wie funktioniert ein Completion-Handler auf iOS?
So habe ich diesen Code im Internet über den alten twitter Rahmen:
[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 haben wir eine Methode aufrufen, die Sachen tut (führt TWRequest) und kehrt zurück, wenn mit response & urlResponse & Fehler beendet. Nur wenn es zurückkehrt, führt es den Block aus, der die gewährten Tests zulässt, und stoppt den Aktivitätsindikator. PERFEKT!
Nun ist dies ein Setup, das ich für eine andere App haben, die funktioniert, aber ich versuche, die Stücke zusammen zu stellen:
@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 performRequestWithHandler
- ist dies leider ein wenig komplexer, weil es einen GCD Anruf im Weg ist ...
Aber im Grunde wird die Anfrage ausgeführt und der Fehler behandelt, die Daten behandelt und dann der Handler überprüft. Meine Frage ist, wie funktioniert dieser Handler Teil? Ich verstehe, wenn es existiert, dann wird es zurück zur Hauptwarteschlange senden und das usersArray zurückgeben. Aber wie kann es warten, bis usersArray aufgefüllt ist? Ich denke, was mich verwirrt, ist die Tatsache, dass die Methode: Block in diesem Fall einen anderen Block in sich hat, den Dispatch_Async-Aufruf. Ich denke, was ich suche, ist die Logik, die wirklich Sachen macht und weiß, WANN die AntwortData und URLResponse zurückgeben. Ich weiß, dass es nicht die gleiche App ist, aber ich kann den Code für performRequestWithHandler nicht sehen.
2 Fragen: (1) Warum sagen Sie in Schritt 3 "Zeit vergeht, bis die Hintergrundwarteschlange einige freie Ressourcen hat". Warum hätte es keine freien Ressourcen? Gleiches in den Schritten 7/8 mit der Hauptwarteschlange. Warum sollte es keine freien Ressourcen haben und deshalb warten müssen? Und das Wichtigste, wie behandelt "handler" den userArray, um ihn zurückzusenden? Welcher Teil des Codes weist den Handler an, Daten an den Absender zurückzusenden? – marciokoko
Siehe meine bearbeitete Antwort. – deekay
Was muss "NSData" in "NSString" und dann zurück in "NSData" konvertiert werden? – Rishab