Подтвердить что ты не робот

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 не запускается

Кто-нибудь сталкивается с подобной проблемой, как я?

4b9b3361

Ответ 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