applicationWillTerminate, когда он вызывается, а когда нет
Привет, я прочитал несколько вопросов на SO о том, что applicationWillTerminate вызывается и не вызывается.
Я хотел обобщить то, что я понял, поскольку есть несколько постов, которые говорят по-разному.
Для IOS (без многозадачности) он вызывается всегда, когда нажата кнопка home.
Для IOS 4 и выше
а. не вызывается при нажатии кнопки "домой" (поскольку приложение переходит в фоновый режим)
б. он вызывается при закрытии приложения из многозадачной док-станции, и если у приложения внезапный флаг завершения в файле info.plist отключен, в противном случае он не вызывается. (Я установил "Приложение должно получать события App Died", и даже тогда при закрытии приложения из многозадачной док-станции функция завершения не вызывалась)
Исходя из этого у меня было несколько вопросов
Это хорошая практика, чтобы установить, что приложение должно получить флаг событий App Died? (Я установил "Приложение должно получать события App Died", и даже тогда при закрытии приложения из многозадачной док-станции функция завершения не вызывалась)
или же
Является ли регистрация для "UIApplicationWillTerminateNotification" лучше, чем настройка info.plist?
По сути, мне нужно выполнять какую-то работу только тогда, когда приложение завершается, а НЕ когда оно переходит в фоновый режим.
или же
РЕДАКТИРОВАТЬ (1): Когда приложение завершается, в приложение отправляется следующее. Как мне это поймать?
Программа получила сигнал: "SIGKILL".
РЕДАКТИРОВАТЬ (2):
Обратите внимание: это не вызывается в IOS 4 и выше при удалении из дока многозадачности. Вы можете подумать, что это так. Но в моем случае это не так.
Я спрашиваю, знает ли кто-нибудь почему? Есть ли что-то еще, что я пропускаю.
Также обратите внимание, что я установил "Приложение должно получать события App Died", и даже тогда оно не вызывается.
РЕДАКТИРОВАТЬ (3):
Ответ на следующий вопрос также не сработал. applicationWillTerminate не вызывается
Кто-нибудь сталкивался с такой же проблемой, как я?
6 ответов
Короче, если у вас нет UIApplicationExitsOnSuspend
в вашем Info.plist, установленном на YES, в iOS4 и выше нет гарантии, что applicationWillTerminate:
когда-нибудь позвонят.
Как сказано в документации:
Для приложений, которые поддерживают фоновое выполнение, этот метод обычно не вызывается, когда пользователь выходит из приложения, потому что в этом случае приложение просто переходит в фоновый режим. Тем не менее, этот метод может быть вызван в ситуациях, когда приложение работает в фоновом режиме (не приостановлено), и система должна прекратить его по некоторым причинам.
(Акцент мой.)
Если вам нужно что-то сделать до выхода из приложения, вам нужно сделать это в applicationDidEnterBackground:
, Нет возможности поймать SIGKILL.
Я вижу -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 ситуации, когда ваше приложение умрет.
Завершено конечным пользователем, вы можете сделать что-то в
-[UIApplication applicationWillEnterBackground:]
, в таком случае,-[UIApplication applicationWillTerminate:]
НЕ будет называться.Сброс системы, например, памяти недостаточно, вы можете сделать что-то в
-[UIApplication applicationWillTerminate:]
в этом случае мы НЕ знаем,applicationWillEnterBackground:
был вызван;Сбой, ничего не может быть сделано, кроме как с помощью какого-либо инструмента отчетности о сбоях. (Отредактировано: ловить
SIGKILL
невозможно)
Источник: http://www.cocos2d-iphone.org/forum/topic/7386
Я скопировал код сохранения состояния из applicationWillTerminate в applicationDidEnterBackground, а также добавил логическое значение multitaskingEnabled, чтобы вызывать сохранение состояния только в applicationDidEnterBackground. ПОТОМУ ЧТО есть один экземпляр на многозадачном устройстве, где вызывается applicationWillTerminate: если приложение находится на переднем плане, и вы выключаете устройство. В этом случае и applicationDidEnterBackground, и applicationWillTerminate вызываются.
Поскольку мы знаем, что приложение имеет только 5 секунд, когда -applicationWillTerminate
будучи призванным Так что если кто-то хочет обновить сервер в этот момент. Чем использовать синхронный вызов.
[NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&error];
Заметка:- -applicationWillTerminate
не будет звонить, если приложение будет убито из приостановленного состояния. Приостановленное состояние означает, что приложение не работает в backgroupd. Одним из решений для этого является использование фоновой задачи.
На основании теста Эндрю я понимаю, что документы для applicationWillTerminate(_:) должны иметь следующие пояснения:
Для приложений, которые не поддерживают фоновое выполнение или связаны с iOS 3.x или более ранней версией, этот метод всегда вызывается, когда пользователь выходит из приложения. Для приложений, поддерживающих фоновое выполнение, этот метод обычно не вызывается [сразу], когда пользователь выходит из приложения, потому что в этом случае приложение просто переходит в фоновый режим. Однако этот метод может быть вызван [вместо beginBackgroundTask(expirationHandler:)] в ситуациях, когда приложение работает в фоновом режиме (не приостановлено) и системе по какой-то причине необходимо завершить его.
// абсолютный ответ applicationWillTerminate
func applicationWillTerminate (application: UIApplication) {
print("applicatoinWillTerminate")
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
Шаг 1: команда + Shift + H (двойной щелчок (вкладка))
шаг 2: переместить верхнюю часть приложения (убить)
шаг 3: applicationWillTerminate Work