Когда вызывать completionHandler в приложении: performFetchWithCompletionHandler: когда фоновая выборка асинхронна?
у меня есть приложение, которое загружает данные в фоновом режиме с помощью выборки фона.
Итак, если фоновая выборка должна иметь место my application:performFetchWithCompletionHandler:
метод называется. В этом методе я использую NSURLConnection для получения асинхронного содержимого.
в моей текущей реализации я только запускаю запрос, а затем вызываю completionHandler
С UIBackgroundFetchResultNewData
. Я знаю, что это неправильно. Поэтому мой вопрос в том, как я правильно называю completionHandler
когда асинхронный запрос завершается в connection:didReceiveData:
метод.
1 ответов
вы правы - вы должны вызвать обработчик завершения только тогда, когда ваша выборка фактически завершена. В противном случае iOS, вероятно, вернет ваше приложение в спящий режим до завершения соединения, и приложения фактически не смогут определить UIBackgroundFetchResultNewData
и UIBackgroundFetchResultNoData
или UIBackgroundFetchResultFailed
во всяком случае до тех пор. Откуда вы знаете, что ваша связь будет успешной?
вам нужно держать completionHandler и вызывать его только после завершения соединения. Скорее всего вы захотите добавьте переменную экземпляра в делегат, скопируйте туда обработчик завершения и вызовите его, когда закончите.
в сторону: connection:didReceiveData:
не сигнализирует о завершении запроса. Согласно документации:
отправлено как соединение загружает данные постепенно.
[...]
делегат должен объединить содержимое каждого объекта данных поставляется для создания полных данных для Загрузки URL-адреса.
появляется любое количество вызовов и конечный результат URL-соединения-это накопление всех из них.
EDIT: вы сохраняете блок, создавая переменную экземпляра правильного типа и копирование блок к нему. Блоки имеют необычную семантику, потому что, в отличие от любого другого объекта Objective-C, они изначально создаются в стеке. Чистый эффект заключается в том, что вы всегда copy
них. Если они находятся в стеке, когда вы копируете, они попадают в кучу. Если они уже в куче тогда копия просто действует как сохранение, так как блоки всегда неизменяемы в любом случае.
так:
@implementation XXMDYourClass
{
// syntax follow the C rule; read from the centre outwards
void (^_completionHandler)(UIBackgroundFetchResult);
}
- (id)initWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
self = [super init];
if(self)
{
// keep the block by copying it; release later if
// you're not using ARC
_completionHandler = [completionHandler copy];
}
return self;
}
- (void)somethingThatHappensMuchLater
{
_completionHandler(UIBackgroundFetchResultWhatever);
}
@end