У меня есть UITableViewController
, о котором я хотел бы уведомить, когда данные соответствующей модели будут готовы к отображению. . Проблема в том, что эти данные извлекаются из веб-службы, и запрос может занять до нескольких секунд. В настоящее время я получаю данные синхронно в основном потоке, что, конечно же, вызывает блокировку моего основного потока. Теперь я не хочу, чтобы мой контроллер ничего знал о загрузке данных из Интернета. Как я могу этого добиться. В настоящее время я думаю об использовании GCD и реализации такого метода, как -loadDataWithCallback:
, и предоставления обратного вызова, который в случае успеха запускает [tableView reloadData]
. Это хороший подход? Есть ли другие возможности сообщить контроллеру, что модель готова? Другая идея, которая у меня была, заключалась в использовании механизма делегирования и настройке контроллера в качестве делегата моей модели?
Подводя итог, что лучше: GCD с обратными вызовами или реализация собственного механизма делегирования?
Есть ли другие возможности?
Обновление : 24 июня 2011 г., 13:15 CET
Прочитав все ваши ответы, я пришел к выводу, что есть 3 возможных решения моей проблемы:
Используйте NSNotifications
и используйте NSURLConnection
для реализации async. скачать
Реализуйте собственный протокол и используйте механизм делегирования. Снова используйте NSURLConnection
для реализации async. загрузка.
Используйте синхронную загрузку в отдельной очереди GCD и используйте обратные вызовы.
Поскольку никто не поддерживает последнее решение, я хочу обсудить этот подход немного подробнее. После просмотра всего кода, который участвует в обработке уведомлений, я думаю, что GCD - лучший подход. Вместо согласования определенного уведомления, которое должно быть каким-то образом задокументировано, чтобы каждый разработчик знал об этом, я могу просто использовать обратный вызов. С одной стороны, это дает мне понятный интерфейс, подобный тому, который у меня был бы при использовании делегата, с другой стороны, это дает мне полную гибкость. Вы действительно думаете, что GCD слишком сложен для этого? Вот мой код:
- (void)loadRestaurantsWithCallback:(void (^)())callback
{
dispatch_queue_t current_queue = dispatch_get_current_queue();
dispatch_queue_t download_queue = dispatch_queue_create("Download queue", NULL);
dispatch_async(download_queue, ^{
self.restaurants = [self loadRestaurants];
dispatch_async(current_queue, ^{ callback(); });
});
dispatch_release(download_queue);
}
Между прочим, мое приложение просто отображает меню различных столовых в моем университете.
В моем контроллере я просто делаю следующее:
if (![self.canteen hasRestaurants]) {
[self.canteen loadRestaurantsWithCallback:^{
[self.tableView reloadData];
}];
}
Это работает как шарм. Что вы думаете об этом решении?
Обновление : 24 июня 2011 г., 16:30 CET
Существует четвертое решение этой проблемы, и, вероятно, это правильный путь, даже если он включает больше кода, чем Подход НОД.Вот что я придумал:
Используйте NSURLConnection
для асинхронной загрузки.
Пусть ваша модель отвечает на обратные вызовы, отправленные экземпляром NSURLConnection
.
Используйте Кодирование значения ключа и Наблюдение за значением ключа .
В вашем контроллере вам просто нужно сделать следующее:
[self.model addObserver:self forKeyPath:@"method-name" options:0 context:NULL];
и
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
[self.tableView reloadData];
}