Вопрос

Я программирую приложение для iPhone, и мне нужно принудительно завершить его из-за определенных действий пользователя.После очистки памяти, выделенной приложением, какой подходящий метод вызвать для завершения работы приложения?

Это было полезно?

Решение

Вы пробовали exit(0)?

В качестве альтернативы, [[NSThread mainThread] exit], хотя я не пробовал, это кажется более подходящим решением.

Другие советы

На iPhone нет концепции выхода из приложения.Единственное действие, которое должно привести к завершению работы приложения, - это нажатие кнопки "Домой" на телефоне, а это не то, к чему разработчики имеют доступ.

По мнению Apple, ваше приложение не должно завершаться само по себе.Поскольку пользователь не нажал кнопку "Домой", любой возврат к главному экрану создает у пользователя впечатление, что ваше приложение вышло из строя.Это сбивающее с толку, нестандартное поведение, и его следует избегать.

выход (0) отображается пользователю как сбой, поэтому покажите пользователю сообщение с подтверждением.После подтверждения приостановите (программно нажмите кнопку "Домой") и подождите 2 секунды, пока приложение перейдет в фоновый режим с анимацией, затем выйдите из режима просмотра пользователем.

-(IBAction)doExit
{
    //show confirmation message to user
    UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Confirmation"
                                                 message:@"Do you want to exit?"
                                                delegate:self
                                       cancelButtonTitle:@"Cancel"
                                       otherButtonTitles:@"OK", nil];
    [alert show];
}

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex != 0)  // 0 == the cancel button
    {
        //home button press programmatically
        UIApplication *app = [UIApplication sharedApplication];
        [app performSelector:@selector(suspend)];

        //wait 2 seconds while app is going background
        [NSThread sleepForTimeInterval:2.0];

        //exit app when app is in background
        exit(0);
    }
}

На самом деле это не способ выйти из программы, а способ заставить людей уйти.

UIAlertView *anAlert = [[UIAlertView alloc] initWithTitle:@"Hit Home Button to Exit" message:@"Tell em why they're quiting" delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
[anAlert show];

Ознакомьтесь с вопросами и ответами здесь: https://developer.apple.com/library/content/qa/qa1561/_index.html

Q:Как мне программно завершить работу моего приложения для iOS?

Не существует API для корректного завершения работы приложения iOS.

В iOS пользователь нажимает кнопку "Домой", чтобы закрыть приложения.Если в вашем приложении есть условия, при которых оно не может обеспечить свою предполагаемую функцию, рекомендуемый подход заключается в отображении предупреждения для пользователя, указывающего на характер проблемы и возможные действия, которые пользователь мог бы предпринять — включение Wi-Fi, включение служб определения местоположения и т.д.Разрешить пользователю завершить работу приложения по своему собственному усмотрению.

ПРЕДУПРЕЖДЕНИЕ: Не вызывайте exit функция.Приложения, вызывающие exit пользователю будет казаться, что произошел сбой, вместо того чтобы выполнить изящное завершение и анимацию обратно на начальный экран.

Кроме того, данные могут не быть сохранены, поскольку -applicationWillTerminate: и подобные UIApplicationDelegate методы не будут вызваны, если вы вызовете exit .

Если во время разработки или тестирования необходимо завершить работу вашего приложения, abort функция, или assert рекомендуется использовать макрос

Перейдите в свой info.plist и отметьте пункт "Приложение не запускается в фоновом режиме".На этот раз, когда пользователь нажимает кнопку "Домой", приложение полностью завершает работу.

Добавить UIApplicationExitsOnSuspend собственность на application-info.plist Для true.

После некоторых тестов я могу сказать следующее:

  • использование частного интерфейса : [UIApplication sharedApplication] приведет к тому, что приложение будет выглядеть так, как будто оно вышло из строя, НО оно вызовет - (void)applicationWillTerminate:(UIApplication *)application прежде чем сделать это;
  • используя exit(0); также завершит работу приложения, но это будет выглядеть "нормально" (значки springboard отображаются, как и ожидалось, с эффектом уменьшения масштаба), но это не вызовет - (void)applicationWillTerminate:(UIApplication *)application метод делегирования.

Мой совет:

  1. Вручную вызовите - (void)applicationWillTerminate:(UIApplication *)application на делегате.
  2. Звонить exit(0);.

Ваш ApplicationDelegate получает уведомление о намеренном выходе пользователя:

- (void)applicationWillResignActive:(UIApplication *)application {

Когда я получаю это уведомление, я просто звоню

        exit(0);

Который выполняет всю работу.И самое лучшее, что пользователь намерен выйти, вот почему это не должно быть проблемой при вызове его там.

В моем аудиоприложении было необходимо выйти из приложения после того, как люди синхронизировали свое устройство, пока музыка все еще играла.Как только синхронизация будет завершена, я получу уведомление.Но выход из приложения сразу после этого на самом деле выглядел бы как сбой.

Поэтому вместо этого я установил флаг, чтобы ДЕЙСТВИТЕЛЬНО выйти из приложения при следующем фоновом действии.Это нормально для обновления приложения после синхронизации.

Недавно мое приложение было отклонено из-за того, что я использовал недокументированный метод.Буквально:

"К сожалению, он не может быть добавлен в App Store, поскольку использует частный API.Использование непубличных API, которые, как указано в разделе 3.3.1 Лицензионного соглашения с программой для разработчиков iPhone, запрещены:

"3.3.1 Приложения могут использовать только документированные API-интерфейсы в порядке, предписанном Apple, и не должны использовать или вызывать какие-либо частные API".

Непубличный API, который включен в ваше приложение, называется terminateWithSuccess"

Яблоко говорит:

"Предупреждение:Не вызывайте функцию exit.Приложения, вызывающие exit, будут казаться пользователю аварийными, вместо того чтобы выполнить изящное завершение и анимацию возврата к главному экрану ".

Я думаю, что это неверное предположение.Если пользователь нажмет кнопку выхода и появится сообщение, в котором говорится что-то вроде:"Приложение теперь завершит работу"., похоже, что оно не разбилось.Apple должна предоставить действительный способ выхода из приложения (не exit (0)).

На это был получен хороший ответ, но решили немного расширить:

Вы не сможете получить одобрение вашего приложения в AppStore, не ознакомившись должным образом с Рекомендациями Apple по пользовательскому интерфейсу iOS.(они сохраняют за собой право отказать вам в выполнении что угодно против них) Раздел "Не завершать работу программно" http://developer.apple.com/library/ios/#DOCUMENTATION/UserExperience/Conceptual/MobileHIG/UEBestPractices/UEBestPractices.html это точное руководство по тому, как вы должны вести себя в этом случае.

Если у вас когда-нибудь возникнет проблема с платформой Apple, для которой вы не можете легко найти решение, обратитесь к HIG.Возможно, Apple просто не хочет, чтобы вы это делали, и обычно они (я не Apple, поэтому не могу гарантировать, что всегда) говорят об этом в своей документации.

Мы не можем выйти из приложения, используя exit(0), abort() функций, поскольку Apple настоятельно не рекомендует использовать эти функции.Хотя вы можете использовать эти функции для целей разработки или тестирования.

Если во время разработки или тестирования необходимо завершить работу вашего приложения рекомендуется использовать функцию прерывания или макрос assert

Пожалуйста, найдите это Яблоко Q&A поток для получения дополнительной информации.

Поскольку использование этой функции создает впечатление, что приложение выходит из строя.Итак, у меня появилось некоторое предложение, например, мы можем отображать оповещение с сообщением о завершении для осведомленного пользователя о закрытии приложения из-за недоступности определенной функциональности.

Но руководство по человеческому интерфейсу iOS для Запуск И остановка приложения, предполагая , что Никогда не используйте кнопку "Выйти" или "Закрыть" чтобы завершить работу приложения.Скорее всего, они предлагают отобразить правильное сообщение, чтобы объяснить ситуацию.

Приложение для iOS никогда не отображает опцию "Закрыть" или "Выйти".Пользователи перестают пользоваться приложением, когда переключаются на другое приложение, возвращаются к главному экрану или переводят свои устройства в спящий режим.

Никогда не выходите из приложения iOS программным путем.Люди склонны интерпретировать это как катастрофу.Если что-то мешает вашему приложению функционировать должным образом по назначению, вам нужно рассказать пользователям о ситуации и объяснить, что они могут с этим поделать.

В дополнение к вышеприведенному хорошему ответу, который я просто хотел добавить, подумайте об очистке своей памяти.

После завершения работы вашего приложения iPhone OS автоматически очистит все, что осталось в вашем приложении, поэтому освобождение всей памяти вручную может просто увеличить время, необходимое вашему приложению для завершения работы.

Хм, возможно, вам "придется" выйти из приложения, если, скажем, вашему приложению требуется подключение к Интернету.Вы могли бы отобразить оповещение, а затем сделать что-то вроде этого:

if ([[UIApplication sharedApplication] respondsToSelector:@selector(terminate)]) {
    [[UIApplication sharedApplication] performSelector:@selector(terminate)];
} else {
    kill(getpid(), SIGINT); 
}
- (IBAction)logOutButton:(id)sender
{
   //show confirmation message to user
   CustomAlert* alert = [[CustomAlert alloc] initWithTitle:@"Confirmation" message:@"Do you want  to exit?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
   alert.style = AlertStyleWhite;
   [alert setFontName:@"Helvetica" fontColor:[UIColor blackColor] fontShadowColor:[UIColor clearColor]];
   [alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{

   if (buttonIndex != 0)  // 0 == the cancel button
   {
      //home button press programmatically
      UIApplication *app = [UIApplication sharedApplication];
      [app performSelector:@selector(suspend)];
      //wait 2 seconds while app is going background
      [NSThread sleepForTimeInterval:2.0];
      //exit app when app is in background
      NSLog(@"exit(0)");
      exit(0);
  }
}

Я использовал подход [[NSMutableArray new] AddObject: nil], упомянутый выше, для принудительного завершения (аварийного завершения) приложения без выполнения контрольного вызова функции exit (0).

Почему?Потому что мое приложение использует закрепление сертификата во всех вызовах сетевого API для предотвращения атак "человек посередине".К ним относятся вызовы инициализации, выполняемые моим финансовым приложением при запуске.

Если проверка подлинности сертификата завершается неудачей, вся моя инициализация вызывает ошибку и оставляет мое приложение в неопределенном состоянии.Разрешение пользователю вернуться домой, а затем обратно в приложение не помогает, так как, если приложение не было удалено операционной системой, оно по-прежнему неинициализировано и ненадежно.

Итак, в данном случае мы сочли лучшим вывести предупреждение, информирующее пользователя о том, что приложение работает в небезопасной среде, а затем, когда пользователь нажмет "Закрыть", принудительно завершить работу приложения, используя вышеупомянутый метод.

[[UIApplication sharedApplication] terminateWithSuccess];

Он работал нормально и автоматически вызывал

- (void)applicationWillTerminateUIApplication *)application delegate.

чтобы удалить предупреждение во время компиляции, добавьте этот код

@interface UIApplication(MyExtras)
  - (void)terminateWithSuccess;
@end 

Пользователь должен решить, когда приложение завершит работу.Я не думаю, что это хорошее взаимодействие с пользователем, когда приложение завершает работу.Поэтому для этого нет хорошего API, он есть только у кнопки home.

Если произошла ошибка:Внедрите это лучше или уведомите пользователя.Если потребуется перезапуск:Реализуйте это лучше, чем уведомлять пользователя.

Звучит глупо, но выходить из приложения, не позволив пользователю принять решение и не уведомив его, - плохая практика.И поскольку для взаимодействия с пользователем есть кнопка "Домой", заявляет Apple, для одной и той же функции (выхода из приложения) не должно быть двух вещей.

Выход из приложения другим способом, чем кнопка "Домой", является действительно не в стиле iOS подходите.

Однако я сделал этот помощник, который не использует никаких личных вещей:

void crash()
{ [[NSMutableArray new] addObject:NSStringFromClass(nil)]; }

Но в моем случае он все еще не предназначен для производства.Он предназначен для тестирования отчетов о сбоях или для быстрого перезапуска после сброса основных данных.Просто сделал безопасным, чтобы не быть отклоненным, если функция останется в производственном коде.

Swift 4.2 (или более поздней версии)

Библиотека под названием Darvin может быть использован.

import Darwin

exit(0) // Here you go

ПРИМЕЧАНИЕ:Это не рекомендуется в приложениях для iOS.

Сделав это, вы получите журнал сбоев.

Вы не должны напрямую вызывать функцию exit(0) так как это немедленно завершит работу приложения и будет выглядеть так, как будто ваше приложение вышло из строя.Поэтому лучше показать пользователям оповещение о подтверждении и позволить им сделать это самим.

Swift 4.2

func askForQuit(_ completion:@escaping (_ canQuit: Bool) -> Void) {
    let alert = UIAlertController(title: "Confirmation!", message: "Do you want to quit the application", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Yes", style: UIAlertAction.Style.default, handler: { (action) in
        alert.dismiss(animated: true, completion: nil)
        completion(true)
    }))
    alert.addAction(UIAlertAction(title: "No", style: UIAlertAction.Style.cancel, handler: { (action) in
        alert.dismiss(animated: true, completion: nil)
        completion(false)
    }))
    self.present(alert, animated: true, completion: nil)
}

/// Will quit the application with animation
func quit() {
    UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
    /// Sleep for a while to let the app goes in background
    sleep(2)
    exit(0)
}

Использование:

self.askForQuit { (canQuit) in
     if canQuit {
         self.quit()
     }
}

Выйдите из приложения другим способом

Однако я сделал этот помощник, который не использует никаких личных вещей:

Выход (0);

Может оказаться целесообразным выйти из приложения, если это приложение с длительным сроком службы, которое также выполняется в фоновом режиме, например, для получения обновлений местоположения (используя обновления местоположения фоновая возможность для этого).

Например, предположим, что пользователь выходит из вашего приложения, основанного на местоположении, и переводит приложение в фоновый режим с помощью кнопки "Домой".В этом случае ваше приложение может продолжать работать, но может иметь смысл полностью выйти из него.Это было бы хорошо для пользователя (освобождает память и другие ресурсы, которые не нужно использовать), и хорошо для стабильности приложения (т. е.убедитесь, что приложение периодически перезапускается, когда это возможно, для защиты от утечек памяти и других проблем с нехваткой памяти).

Это могло бы (хотя, вероятно, не должно, см. Ниже :-) быть достигнуто с помощью чего-то вроде:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    if (/* logged out */) {
        exit(0);
    } else {
       // normal handling.
    }
}

Поскольку затем приложение завершит работу вне фона это не будет выглядеть неправильно для пользователя и не будет напоминать сбой, при условии, что пользовательский интерфейс будет восстановлен при следующем запуске приложения.Другими словами, для пользователя это ничем не отличалось бы от инициированного системой завершения работы приложения, когда оно находится в фоновом режиме.

Тем не менее, было бы предпочтительнее использовать более стандартный подход, чтобы сообщить системе, что приложение может быть завершено.Например, в этом случае, убедившись, что GPS не используется, прекратив запрашивать обновления местоположения, включая отключение отображения текущего местоположения на карте, если оно присутствует.Таким образом, система позаботится о завершении работы приложения в течение нескольких минут (т.е. [[UIApplication sharedApplication] backgroundTimeRemaining]) после того, как приложение перейдет в фоновый режим.Это дало бы все те же преимущества без необходимости использовать код для завершения работы приложения.

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    if (/* logged out */) {
       // stop requesting location updates if not already done so
       // tidy up as app will soon be terminated (run a background task using beginBackgroundTaskWithExpirationHandler if needed).
    } else {
       // normal handling.
    }
}

И, конечно, используя exit(0) никогда не подойдет для обычного производственного приложения, которое работает на переднем плане, согласно другим ответам, которые ссылаются http://developer.apple.com/iphone/library/qa/qa2008/qa1561.html

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top