AFNetworking-2 waitUntilFinished nicht funktioniert
Ich weiß, es ist eine ähnliche Frage, aber es ist für eine ältere version von AFNetworking, und nicht wirklich Antwort es trotzdem.
Ich habe den folgenden code:
AFHTTPRequestOperationManager* manager = [AFHTTPRequestOperationManager manager];
manager.securityPolicy.allowInvalidCertificates = YES;
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername: currentUser() password: currentPassword()];
__block NSDictionary* response = nil;
AFHTTPRequestOperation* operation = [manager
GET: @"https://10.20.30.40:8765/foobar"
parameters: [NSDictionary dictionary]
success:^(AFHTTPRequestOperation* operation, id responseObject){
response = responseObject;
NSLog(@"response (block): %@", response);
}
failure:^(AFHTTPRequestOperation* operation, NSError* error){
NSLog(@"Error: %@", error);}
];
[operation waitUntilFinished];
NSLog(@"response: %@", response);
...
Wenn ich dieses, was ich werde sehen, in meinem log steht:
2013-12-09 09:26:20.105 myValve[409:60b] response: (null)
2013-12-09 09:26:20.202 myValve[409:60b] response (block): {
F00005 = "";
F00008 = "";
F00013 = "";
}
Den NSLog
ist nach die waitUntilFinished
feuert zuerst. Ich erwartet, dass es Feuer Sekunde. Was bin ich?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ein paar Gedanken:
Das Problem ist, dass
waitUntilFinished
wird warten, bis die core-Netzwerk-Betrieb abgeschlossen, aber es wird nicht warten für diesuccess
oderfailure
Abschluss blockiert. Wenn Sie wollen, warten Sie für die Fertigstellung der Blöcke, die Sie verwenden können, ein semaphore:Können Sie alternativ wickeln Sie diese in Ihrem eigenen gleichzeitigen
NSOperation
Unterklasse, die EntsendungisFinished
imAFHTTPRequestOperation
Fertigstellung der Blöcke, wodurch diesemaphore
im Prozess.Beachten Sie, stellen Sie sicher, dass Sie
completionQueue
wenn dies die Semaphore, auf die main queueweil, in der Abwesenheit von, dass, AFNetworking standardmäßig Versand completion-Handler, um die Haupt-Warteschlange und Sie können den deadlock.
Nebenbei, man sollte niemals blockieren die wichtigste queue (schlechte UX, Ihre app könnte getötet werden durch watchdog-Prozess, etc.), also, wenn Sie tun dies aus der main queue, würde ich raten von der Verwendung von entweder
waitUntilFinished
oder semaphore. Es ist besser, nur zu initiieren, was auch immer Sie benötigen, aus in der Ausführung blockiert, so dass der Haupt-queue-Ausführung fortsetzen, während das asynchrone Netzwerk im Laufenden Betrieb, z.B.:Klingt es wie Sie wollen, lassen Sie Ihr Modell lassen sich die UI-tun Sie alle erforderlichen updates, wenn das model-Objekt ist fertig, macht seine updates. So können Sie Ihre eigenen block Parameter, so dass der view controller kann sagen, das Modell-Objekt, was zu tun ist, wenn Ihre getan (anstelle von
waitUntilFinished
oder semaphore, um die Netzwerk-operation-block der main-queue). Zum Beispiel, nehmen wir an, dein Modell hatte eine Methode wie diese:Dann Ihre view-controller etwas tun zu können:
Bottom line kann Ihr code mit dem gleichen Stil der Abschluss-Blöcke, die AFNetworking verwendet. Wenn Sie möchten, dass das Modell zur Weiterleitung von Informationen zurück, können Sie fügen Sie zusätzliche Parameter für die Fertigstellung der Blöcke selbst, aber ich nehme an, der oben veranschaulicht die grundlegende Idee.
updateModel
- Methode-block-Parameter (nicht im Gegensatz zu densuccess
undfailure
Blöcke, AFNetworking, selbst, verwendet werden). So, die view-controller sagen kann, effektiv, "Aktualisierung des Modells, und wenn Sie fertig sind, x zu tun, y, und z". Siehe überarbeitete Antwort.completionQueue
Eigenschaft (die ich in einer pull-request vor ein paar Monaten).