Próbuję zrozumieć bloki obsługi ukończeń &. Sądzę, że można używać bloków do wielu głębokich rzeczy programistycznych bez programów obsługi zakończenia, ale myślę, że rozumiem, że programy obsługi zakończenia są oparte na blokach. (Tak więc w zasadzie programy do obsługi zakończenia wymagają bloków, ale nie odwrotnie).Jak działa moduł obsługi zakończenia w systemie iOS?
Więc widziałem ten kod w internecie o starych ram Twitterze:
[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;
}];
Tutaj wzywamy metodę, która robi rzeczy (wykonuje TWRequest) i powraca po zakończeniu z responseData & urlResponse & błędu. Dopiero po zwrocie wykonuje blok, który uzyskały testy, i zatrzymuje wskaźnik aktywności. IDEALNY!
Teraz jest to konfiguracja mam dla innej aplikacji, która działa, ale próbuję umieścić kawałki razem:
@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);
});
}
});
}
Oto moje rozumienie:
- fetchUsersWithCompletionHandler jest oczywiście homologa performRequestWithHandler
- Niestety jest to trochę bardziej skomplikowane, ponieważ istnieje wywołanie GCD w sposób ...
Zasadniczo żądanie jest wykonywane, a błąd jest przetwarzany, dane są przetwarzane, a następnie sprawdzany jest program obsługi. Moje pytanie brzmi: jak działa ta część obsługi? Rozumiem, że jeśli istnieje, to odeśle z powrotem do głównej kolejki i zwróci obiekt usersArray. Ale skąd wiadomo, że trzeba poczekać, aż zapełni się userArray? Domyślam się, że mylące jest to, że metoda: block w tym przypadku ma inny blok w sobie, wywołanie dispatch_async. Domyślam się, że to, czego szukam, to logika, która faktycznie robi rzeczy i wie, KIEDY zwracać responseData i urlResponse. Wiem, że to nie ta sama aplikacja, ale nie widzę kodu dla performRequestWithHandler.
2 pytania: (1) dlaczego mówisz w kroku 3 "czas mija, aż kolejka tła ma trochę wolnych zasobów". Dlaczego NIE miałoby wolnych zasobów? to samo w krokach 7/8 z główną kolejką. Dlaczego NIE miałby wolnych zasobów i musiałby czekać? I najważniejsze, w jaki sposób handler "obsługuje" tablicę usersArray, aby ją odesłać? Jaka część kodu mówi handlerowi, aby przesłać dane do tego, kto go nazwał? – marciokoko
Zobacz moją zmienioną odpowiedź. – deekay
Jaka jest potrzeba konwersji 'NSData' na' NSString', a następnie z powrotem do 'NSData'? – Rishab