Это исключение возникает, когда фоновая задача не завершена вовремя. Хотя я не могу быть уверен на 100%, я полагаю, что именно этот сбой происходит из-за блока, который вы передаете в beginBackgroundTaskWithExpirationHandler:
, который вызывается, если соединение еще не завершено, и система хочет завершить вашу фоновую задачу.
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}];
Документация - (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void (^)(void))handler
говорит о handler
: «Вы должны использовать этот обработчик, чтобы очистить и отметить конец фоновой задачи».
Вы фактически не завершаете задачу, когда этот блок вызывается из-за вызова dispatch_async
. Вы не завершите задачу, пока не вернется этот вызов блока (и ваш блок dispatch_async
не будет запущен). Я считаю, что в большинстве случаев у вас есть достаточно времени для запуска второго блока, прежде чем сторожевой таймер выключит ваше приложение, но иногда его нет. Итак, вам нужно сразу же завершить фоновую задачу, а затем выполнить dispatch_async
для любой другой очистки, которую вам нужно сделать:
UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier tid = bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:tid];
dispatch_async(dispatch_get_main_queue(), ^{
bgTask = UIBackgroundTaskInvalid;
});
}];
Кроме того, в документации сказано: «Обработчик вызывается синхронно в главном потоке», поэтому вам действительно не нужно выполнять dispatch_async
. Вы можете просто сделать:
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];