Когда будет вызвано applicationWillTerminate?
В каких ситуациях будет вызываться applicationWillTerminate? Например, будет ли он иногда вызываться в случае сбоя в коде?
Документ Apple по этому вопросу расплывчат, он говорит только тогда, когда система должна прекратить его по какой-то причине.
Для приложений, которые не поддерживают фоновое выполнение или связаны с iOS 3.x или более ранней версией, этот метод всегда вызывается, когда пользователь выходит из приложения. Для приложений, которые поддерживают фоновое выполнение, этот метод обычно не вызывается, когда пользователь выходит из приложения, потому что в этом случае приложение просто перемещается в фоновый режим. Однако этот метод может быть вызван в ситуациях, когда приложение работает в фоновом режиме (не приостановлено), и система по какой-то причине должна прекратить его.
5 ответов
Я только что исследовал этот вопрос (iOS 9.2). И у меня есть некоторые результаты.
Так, applicationWillTerminate
вызывается, когда пользователь закрывает приложение, не переключая его в фоновый режим: приложение активно, пользователь дважды нажимает кнопку "Домой" и выбрасывает приложение.
Но если пользователь сначала переключает приложение в фоновый режим, а затем после этого пытается завершить приложение, applicationWillTerminate
не будет называться.
Вы можете проверить это:
- (void)applicationWillTerminate:(UIApplication *)application {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"term"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
а также
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"term"]){
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"term"];
[[NSUserDefaults standardUserDefaults] synchronize];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"WORKED" message:@"term works" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
[alert show];
}
...
return YES;
}
Начиная с iOS 4, практический ответ - "никогда". Вы не можете предполагать, что это когда-либо будет называться. Обычно случается, что ваше приложение перемещается в фоновый режим, когда пользователь нажимает кнопку "Домой", а затем через несколько секунд оно переходит в "приостановленное состояние" (все еще в памяти, но не получает никакого времени ЦП).
Когда ваше приложение находится в приостановленном состоянии, система может завершить его в любое время без предупреждения (обычно из-за нехватки памяти).
Когда вы отстранены, вы не получаете вызов applicationWillTerminate до того, как вас убьют. Вы должны предположить, что когда вы получаете applicationDidEnterBackground:
сообщение, вы собираетесь быть приостановлено вскоре после этого, и умрете, пока приостановлено. Приведите свои дела в порядок (сохраните состояние приложения.)
В некоторых случаях вы по-прежнему можете получать вызовы applicationWillTerminate, но не следует полагать, что вы это сделаете.
Завершение приложения в соответствии с Руководством по программированию приложения для iOS:
- Приложения должны быть готовы к прекращению в любое время и не должны ждать сохранения пользовательских данных или выполнения других важных задач.
- Завершение, инициируемое системой, является нормальной частью жизненного цикла приложения. Система обычно завершает приложения, чтобы освободить память и освободить место для других приложений, запускаемых пользователем, но система также может завершить приложения, которые неправильно работают или не отвечают на события своевременно.
- Приостановленные приложения не получают уведомления, когда они прекращены; система убивает процесс и восстанавливает соответствующую память.
- Если приложение в настоящее время работает в фоновом режиме и не приостановлено, система вызывает applicationWillTerminate: своего делегата приложения до завершения.
- Система не вызывает этот метод при перезагрузке устройства.
- В дополнение к системе, завершающей ваше приложение, пользователь может явно завершить ваше приложение с помощью многозадачного интерфейса пользователя. Пользовательское завершение имеет тот же эффект, что и завершение приостановленного приложения. Процесс приложения убит, и приложение не отправляет уведомление.
Когда пользователь открывает приложение, а затем нажимает кнопку "Домой", iOS не закрывает приложение, а приостанавливает его и помещает в фоновый режим.
Тем не менее, устройства iOS имеют только 1 ГБ оперативной памяти (в основном), поэтому после открытия и закрытия нескольких приложений они начинают работать.
iOS теперь должна выкинуть некоторые из этих приложений из барана. Таким образом, оно пробуждает (по предположению крупнейшего пользователя оперативной памяти или самого старого использовавшегося приложения) приложение и говорит ему сохранить все, что ему нужно, чтобы закрыть его изящно.
Вот когда -applicationWillTerminate:
называется. Когда iOS закрывает ваше приложение. Конечно, если вы запретите этому методу возвращаться слишком долго, iOS просто все равно убьет ваше приложение (в конце концов, оно нуждается в ресурсах).
Если вы сохраняете все в -willResignActive:
а также -willEnterBackground:
тогда вы можете просто проигнорировать метод, и ваше приложение закроется после возврата метода.
РЕДАКТИРОВАТЬ: Если пользователь говорит переключателю приложения закрыть приложение, он также попытается изящно закрыть ваше приложение. Но если это ситуация, когда устройству нужно больше ресурсов, есть шанс, что вы не получите -applicationWillTerminate:
вызвано, так как устройство не успеет, так как оно может нуждаться в ресурсах быстрее, чем ваше приложение может быть изящно закрыто. Так applicationWillTerminate:
не гарантированно будет вызван.
Быстро используйте делегат в приведенном ниже
optional func applicationWillTerminate(_ application: UIApplication)
Этот метод позволяет вашему приложению узнать, что оно будет завершено и полностью очищено из памяти. Этот метод следует использовать для выполнения любых задач окончательной очистки вашего приложения, таких как освобождение общих ресурсов, сохранение пользовательских данных и аннулирование таймеров. У вашей реализации этого метода есть примерно пять секунд для выполнения любых задач и возврата. Если метод не вернется до истечения времени, система может полностью убить процесс.
Я думаю, что он будет вызываться, когда пользователь убивает приложение с переднего плана или когда ОС делает это самостоятельно. в остальное время это просто большое "возможно". Я обычно не полагаюсь на это из-за этого "возможно".
Вы можете использовать "didEnterBackground", который вызывается более надежным способом.
Вы также можете попытаться создать аварийный отказ и посмотреть, как он отреагирует точно (сбой с переднего плана и фона).