#ios #objective-c #background-process
#iOS #objective-c #фоновый процесс
Вопрос:
Когда мое приложение загружает большой файл и пользователь переключается на другое приложение, я запускаю фоновую задачу следующим образом:
beginBackgroundTaskWithExpirationHandler:
и затем, если пользователь открывает «app switcher» двойным щелчком мыши, снимок экрана моего приложения совершенно случайный. Иногда он показывает контроллер просмотра, который даже не был открыт в приложении.
ignoreSnapshotOnNextApplicationLaunch
не помогает, потому что он вообще не работает.
Apple говорит: Avoid updating your windows and views
здесь: документация, но я не обновляю представления.
Я также запускаю таймер, чтобы проверить, сколько времени осталось в фоновом режиме, и этот таймер является причиной моих проблем. Если я его не создаю, все работает идеально, но я не могу сохранить состояние загрузки в обработчике истечения срока действия — недостаточно времени.
Как я могу избежать этого странного поведения?
-(void)appDidEnterBackground {
UIApplication *application = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier bgTask;
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
if(backgroundTimer == nil || ![backgroundTimer isValid]) {
backgroundTimer = [[NSTimer alloc]
initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:0]
interval:1
target:self
selector:@selector(checkBackgroundTimeRemaining)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:backgroundTimer forMode:NSRunLoopCommonModes];
[[NSRunLoop currentRunLoop] run];
}
}
- (void)checkBackgroundTimeRemaining {
NSTimeInterval timeRemaining = [[UIApplication sharedApplication] backgroundTimeRemaining];
if(timeRemaining < 5) {
if(backgroundTimer != nil) {
[backgroundTimer invalidate];
backgroundTimer = nil;
}
[downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
[self saveResumeData:resumeData];
}];
}
}
Ответ №1:
Иногда он показывает контроллер просмотра, который даже не был открыт в приложении.
Это звучит действительно подозрительно и никогда не должно произойти. Может быть, вы можете добавить какой-нибудь код, чтобы показать, что вы делаете?
ignoreSnapshotOnNextApplicationLaunch здесь неуместен, поскольку он используется только для определения того, что происходит, когда пользователь снова нажимает на ваш значок, чтобы открыть приложение.
Возможно, вы забыли вызвать endBackgroundTask: когда вы закончили фоновую задачу?
Я не уверен, что вы собираетесь делать с таймером? Если необходимо определить, сколько времени осталось для выполнения в фоновом режиме, вместо этого используйте backgroundTimeRemaining UIApplication.
Комментарии:
1. Теперь я избавился от таймера. Я проверяю оставшееся время при загрузке другой части данных. Все еще не могу понять, как таймер может повлиять на работу app switcher.
2. Переключатель приложений просто показывает последнее представление, которое было показано, когда ваше приложение перешло в фоновый режим. Когда вы выполняете выборку в фоновом режиме, она записывается после вызова обработчика завершения в приложении: performFetchWithCompletionHandler: