Я тщательно искал подходящее решение, но оно не сработало:
Приложение для iPhone обновляет данные через запросы NSURL по требованию пользователя. Размер каждого загружаемого файла составляет всего 1,5 КБ, но одно обновление может содержать 400 таких файлов. Поэтому я делаю загрузку в отдельном потоке, который можно отменить, и во время обновления есть UIAlertView с индикацией процесса и кнопкой отмены. Это может продолжаться 1 ... 3 минуты, поэтому оно может превысить время ожидания, пока устройство остается в живых или произойдет что-то другое, и мое приложение перейдет в фоновый режим.
Когда я ничего не делаю при вызове applicationDidEnterBackground , я понимаю, что мое приложение приостановлено, а также рабочий поток. Он просыпается и продолжает работать, когда приложение снова на переднем плане. Все идет нормально. У меня возникают проблемы, когда я снова нажимаю кнопку отмены после того, как снова на переднем плане - тогда поток реагирует как отменяемый (как и должно быть), но сразу же запускается снова и вылетает в конце (с кодами ошибок где-то глубоко в платформах Apple). Он отлично работает, чтобы отменить поток, пока приложение продолжает оставаться на переднем плане - поэтому я хочу остановить / отменить его, когда введено applicationDidEnterBackground . Я пытался сделать что-то для этого, но каждая попытка заканчивается тем, что рабочий поток приостанавливается в тот момент, когда вызывается applicationDidEnterBackground , поэтому я не могу отменить поток и ждать этого. Один пример, который я попробовал, таков:
diagView* viewDiagCtrl = startDiag.diagViewControl;
if (viewDiagCtrl != nil && viewDiagCtrl.actionThread != nil)
{
// UIBackgroundTaskIdentifier bgTask is instance variable
NSAssert(self->bgTask == UIBackgroundTaskInvalid, nil);
bgTask = [application beginBackgroundTaskWithExpirationHandler:
^{
dispatch_async(dispatch_get_main_queue(),
^{
NSLog(@"stopping actions definitely");
[viewDiagCtrl stopBackGroundActivity:self];
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}];
dispatch_async(dispatch_get_main_queue(),
^{
// Start with 10ms time boxes
NSTimeInterval ti = 0.01;
while ([application backgroundTimeRemaining] > 1.0)
{
if (![viewDiagCtrl.actionThread isExecuting])
break;
NSDate* date = [NSDate dateWithTimeIntervalSinceNow:ti];
// Let the current run-loop do it's magif for one time-box.
[[NSRunLoop currentRunLoop] runMode: NSRunLoopCommonModes
beforeDate: date];
// Double the time box, for next try, max out at 1000ms.
ti = MIN(1.0, ti * 2);
}
[viewDiagCtrl stopBackGroundActivity:self];
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}
Я не разбираюсь в материалах всей очереди и где-то нашел такую конструкцию. Я предполагаю, что все отправленные вещи работают в главном потоке, а рабочий поток остается приостановленным, так что у меня нет шансов отменить его. Любые идеи, чтобы прийти с этим?
Я также читал о попытках сделать все без многопоточности - но я не очень ценю это. Может быть, есть какая-нибудь полезная ссылка для правильной обработки ситуации «перейти в фоновый режим»?