Я пытаюсь понять обработчики и блокировки завершения. Я считаю, что вы можете использовать блоки для многих глубоких программных вещей без обработчиков завершения, но я думаю, что понимаю, что обработчики завершения основаны на блоках. (Так что в основном обработчики завершения требуют блоки, но не наоборот).
Итак, я видел этот код в Интернете о старой структуре твиттера:
[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;
}];
Здесь мы вызываем метод, который делает stuff (выполняет TWRequest) и возвращает, когда закончил с responseData и urlResponse и ошибкой. Только когда он возвращает, он выполняет блок, который предоставляет тесты и останавливает индикатор активности. ИДЕАЛЬНОЕ!
Теперь это настройка, которую я использую для другого приложения, которое работает, но я пытаюсь собрать фрагменты:
@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);
});
}
});
}
Вот мое понимание:
- fetchUsersWithCompletionHandler, очевидно, является гомологом executeRequestWithHandler
- К сожалению, это немного сложнее, потому что есть вызов GCD на пути...
Но в основном, запрос выполняется и обрабатывается ошибка, данные обрабатываются, а затем проверяется обработчик. Мой вопрос: как эта часть обработчика работает? Я понимаю, что если он существует, он отправит обратно в основную очередь и вернет userArray. Но как он знает, ждать, пока userArray будет заполнен? Я предполагаю, что меня смущает тот факт, что метод: блок в этом случае имеет другой блок внутри него, вызов dispatch_async. Я предполагаю, что Im ищет логику, которая на самом деле делает вещи и знает, КОГДА возвращать responseData и urlResponse. Я знаю, что это не то же приложение, но я не могу видеть код для выполненияRequestWithHandler.