Когда вызывать 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