ApplicationWillTerminate, когда он вызывается, а когда нет
Привет, я прочитал несколько вопросов о SO о вызове applicationWillTerminate и не вызванном вызове.
Я хотел обобщить то, что понял, поскольку есть несколько сообщений, которые говорят по-другому.
-
Для IOS (без многозадачности) он вызывается всегда, когда нажата кнопка home.
-
Для IOS 4 и выше
а. он не вызывается при нажатии кнопки "домой" (при перемещении приложения к фону)
б. он вызывается при закрытии приложения из многозадачной док-станции и если у приложения есть внезапный флаг завершения в инфо.плите, отключен иначе, он не вызывается. (я установил "Приложение должно получать события App Died", и даже тогда при закрытии приложения из многозадачной док-станции функция завершения не вызывалась)
Основываясь на этом, у меня было несколько вопросов.
Является ли хорошей практикой устанавливать приложение, чтобы получить флаг App Died events? (Я установил "Приложение должно получать App Died events", и даже тогда при закрытии приложения из многозадачной док-станции функция завершения не вызывалась)
или
Является ли регистрация для "UIApplicationWillTerminateNotification" лучше, чем настройка info.plist?
В принципе, мне нужно сделать некоторую работу только тогда, когда приложение завершается, а НЕ, когда оно перемещается на задний план.
или
ИЗМЕНИТЬ (1):
Когда приложение завершается, в APP отправляется следующее. Как его поймать?
Программный сигнал: "SIGKILL".
РЕДАКТИРОВАТЬ (2):
Обратите внимание: он не вызывается в IOS 4 и выше при удалении из многозадачной док-станции. Вы можете подумать, что это так. Но в моем случае это не так.
Я спрашиваю, знает ли кто-нибудь почему? Есть что-то еще, что мне не хватает.
Также обратите внимание, что я устанавливаю "Приложение должно получать события App Died", и даже тогда его не вызывают.
ИЗМЕНИТЬ (3):
Ответ на следующий вопрос также не помог.
applicationWillTerminate не запускается
Кто-нибудь сталкивается с подобной проблемой, как я?
Ответы
Ответ 1
Короче говоря, если у вас нет UIApplicationExitsOnSuspend
в вашем Info.plist равным YES, в iOS4 и выше нет гарантии, что applicationWillTerminate:
когда-либо будет вызван.
Как в документации говорится:
Для приложений, поддерживающих фоновое выполнение, этот метод обычно не вызывается, когда пользователь завершает работу приложения, поскольку приложение просто перемещается на задний план в этом случае. Однако это метод может вызываться в ситуациях, когда приложение работает в фон (не приостановлен), и системе необходимо его прекратить по какой-то причине
(Подчеркните мой.)
Если вам нужно что-то сделать до выхода приложения, вам нужно сделать это в applicationDidEnterBackground:
. Невозможно поймать SIGKILL.
Ответ 2
Я вижу, что -applicationWillTerminate:
получает вызов со следующим тестом. В новом проекте (я использовал шаблон Single View Application) добавьте в AppDelegate следующее:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(@"%s", __PRETTY_FUNCTION__);
__block UIBackgroundTaskIdentifier identifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
if (identifier != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:identifier];
identifier = UIBackgroundTaskInvalid;
}
}];
dispatch_async(dispatch_get_main_queue(), ^{
for (int i=0; i < 20; i++) {
NSLog(@"%d", i);
sleep(1);
}
if (identifier != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:identifier];
identifier = UIBackgroundTaskInvalid;
}
});
}
- (void)applicationWillTerminate:(UIApplication *)application
{
NSLog(@"%s", __PRETTY_FUNCTION__);
}
В этом примере будет запущена фоновая задача, когда приложение войдет в фоновый режим. Задача - это просто задержка в 20 с (с регистрацией один раз в секунду), которая удерживает приложение в фоновом режиме (обратите внимание на разницу между запуском в фоновом режиме и приостановлено) достаточно долго, чтобы его можно было убить из переключателя приложений.
Итак, чтобы протестировать его, запустите приложение, нажмите кнопку "домой", чтобы отправить приложение на задний план, а затем до истечения 20-секундной задержки удалите приложение из переключателя приложений. По истечении 20 секунд вызывается -applicationWillTerminate:
. Вы можете посмотреть консоль в Xcode, чтобы убедиться, что это так.
Я пробовал это в iOS Simulator для iOS 5.1 и 6.1 (оба iPhone) и видел, что это происходит в обоих случаях. Я также тестировал iPhone 4S с iOS 6.1.2 и видел то же поведение.
Ответ 3
Источник: http://www.cocos2d-iphone.org/forum/topic/7386
Я скопировал свой код сохранения состояния из приложенияWillTerminate в applicationDidEnterBackground, а также добавил многозадачностьEnabled, так что я вызываю только сохранение состояния в applicationDidEnterBackground. ПОТОМУ ЧТО, есть один экземпляр на многозадачном устройстве, где вызывается applicationWillTerminate: если приложение находится на переднем плане и вы отключите устройство. В этом случае вызываются как applicationDidEnterBackground, так и applicationWillTerminate.
Ответ 4
Как я знаю, есть 3 ситуации, когда ваше приложение умрет.
-
Заканчивается конечным пользователем, вы можете сделать что-то в -[UIApplication applicationWillEnterBackground:]
, и в этом случае -[UIApplication applicationWillTerminate:]
НЕ будет вызываться.
-
Выпало из системы, например, недостаточно памяти, вы можете сделать что-то в -[UIApplication applicationWillTerminate:]
, и в этом случае мы НЕ знаем, был ли вызван applicationWillEnterBackground:
:
-
Сбой, ничего не может быть сделано, за исключением использования какого-либо инструмента отчетности о сбоях. (Отредактировано: catching SIGKILL
невозможно)
Ответ 5
Как известно, приложение имеет только 5 секунд при вызове -applicationWillTerminate
. Поэтому, если кто-то хочет обновить сервер в этот момент. Чем пользоваться
Синхронный вызов.
[NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&error];
Примечание. - -applicationWillTerminate
не будет вызываться, если приложение было убито из приостановленного состояния. Приостановленное состояние означает, что приложение ничего не работает в backgroupd. Одним из решений для этого является использование фоновой задачи.
Ответ 6
//приложение абсолютного ответаWillTerminate
func applicationWillTerminate (приложение: UIApplication) {
print("applicatoinWillTerminate")
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
Шаг 1: команда + сдвиг + h (двойной щелчок (вкладка))
шаг 2: переместить верхнюю часть приложения (убить)
шаг 3: applicationWillTerminate Work