退出iPhone应用程序的正确方法?

时间:2008-12-10 05:42:32

标签: ios objective-c iphone cocoa-touch ipad

我正在编写一个iPhone应用程序,我需要强制它退出,因为某些用户操作。清理内存后分配的应用程序,调用终止应用程序的适当方法是什么?

25 个答案:

答案 0 :(得分:270)

在iPhone上没有退出应用程序的概念。导致应用退出的唯一操作是触摸手机上的“主页”按钮,这不是开发人员可以访问的内容。

根据Apple的说法,您的应用不应单独终止。由于用户未点击“主页”按钮,因此返回主屏幕会让用户感觉您的应用已崩溃。这是令人困惑的非标准行为,应该避免。

答案 1 :(得分:212)

您是否尝试过exit(0)

或者,[[NSThread mainThread] exit],虽然我没有尝试过这似乎是更合适的解决方案。

答案 2 :(得分:47)

退出(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);
    }
}

答案 3 :(得分:38)

它不是一种退出计划的方式,而是一种迫使人们戒烟的方法。

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];

答案 4 :(得分:38)

在此处查看问答:https://developer.apple.com/library/content/qa/qa1561/_index.html

  

问:我如何以编程方式退出iOS应用程序?

     

没有为优雅地终止iOS应用程序提供API。

     

在iOS中,用户按Home键关闭应用程序。如果您的应用程序具有无法提供其预期功能的条件,建议的方法是为用户显示警告,指示问题的性质以及用户可能采取的操作 - 打开WiFi,启用位置服务等。允许用户自行决定终止申请。

     
    

警告:请勿调用exit功能。呼叫exit的应用程序对用户来说似乎已经崩溃,而不是执行正常终止并动画回到主屏幕。

  
     

此外,可能无法保存数据,因为如果您调用exit,则不会调用-applicationWillTerminate:和类似的UIApplicationDelegate方法。

     

如果在开发或测试期间有必要终止您的应用程序,建议使用abort函数或assert

答案 5 :(得分:38)

转到info.plist并检查“应用程序不在后台运行”键。这次当用户单击主页按钮时,应用程序将完全退出。

答案 6 :(得分:17)

将application-info.plist上的UIApplicationExitsOnSuspend属性添加到true

答案 7 :(得分:13)

经过一些测试,我可以说以下内容:

  • 使用私人界面:[UIApplication sharedApplication]会导致应用看起来崩溃,但在此之前会调用- (void)applicationWillTerminate:(UIApplication *)application;
  • 使用exit(0);也将终止应用程序,但它看起来“正常”(跳板的图标显示为预期,具有缩小效果),但它不会调用- (void)applicationWillTerminate:(UIApplication *)application代表方法

我的建议:

  1. 手动调用代理上的- (void)applicationWillTerminate:(UIApplication *)application
  2. 致电exit(0);

答案 8 :(得分:8)

您的ApplicationDelegate会收到用户有意退出的通知:

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

当我收到此通知时,我只需致电

        exit(0);

所有工作都做到了。最好的是,这是戒烟的意图,这就是为什么在这里调用它不应该是一个问题。

在我的音频应用程序上,当人们在音乐还在播放时同步他们的设备后,有必要退出应用程序。一旦同步完成,我会收到通知。但是在此之后立即退出应用程序实际上看起来就像崩溃一样。

所以我设置了一个标志,以便在下一次后台操作时真正退出应用程序。在同步后刷新应用程序是可以的。

答案 9 :(得分:6)

我的应用程序最近被拒绝了bc我使用了无证方法。字面上:

“不幸的是,它无法添加到App Store中,因为它使用的是私有API。禁止使用非公开API,如iPhone开发人员计划许可协议第3.3.1节所述:

“3.3.1应用程序只能以Apple规定的方式使用文档化的API,不得使用或调用任何私有API。”

您的应用程序中包含的非公共API是terminateWithSuccess“

答案 10 :(得分:6)

苹果说:

“警告:不要调用退出函数。调用exit的应用程序将显示给用户崩溃,而不是执行正常终止并动画回到主屏幕。”

我认为这是一个不好的假设。如果用户点击退出按钮并显示一条消息,如下所示:“应用程序现在将退出。”,它似乎没有崩溃。 Apple应提供退出应用程序的有效方法(不是退出(0))。

答案 11 :(得分:4)

这得到了一个很好的答案,但决定扩大一点:

如果不仔细阅读Apple的iOS人机界面指南,就无法将您的应用程序接受到AppStore。 (他们保留拒绝您对其进行任何的权利)“不要以编程方式退出”http://developer.apple.com/library/ios/#DOCUMENTATION/UserExperience/Conceptual/MobileHIG/UEBestPractices/UEBestPractices.html部分 在这种情况下,您应该如何对待。

如果您遇到Apple平台问题,则无法轻松找到解决方案,请咨询HIG。 Apple可能根本不希望你这样做,而且他们通常(我不是Apple,所以我总是不能保证)在他们的文档中这样说。

答案 12 :(得分:3)

我们无法使用exit(0)abort()函数退出应用,因为Apple强烈反对使用这些功能。虽然您可以将此功能用于开发或测试目的。

  

如果在开发或测试期间有必要终止您的   建议使用应用程序,中止函数或断言宏

请找到此Apple Q&A主题以获取更多信息。

使用此功能时会产生应用程序崩溃的印象。所以我得到了一些建议,比如我们可以向知名用户显示关于关闭应用程序的终止消息,因为某些功能不可用。

Starting And Stopping App的iOS人机界面指南,建议从不使用退出或关闭按钮来终止应用程序。而不是他们建议显示正确的信息来解释情况。

  

iOS应用程序从不显示“关闭”或“退出”选项。人们停止使用   应用程序切换到另一个应用程序,返回主屏幕,或放   他们的设备处于睡眠模式。

     

永远不要以编程方式退出iOS应用。人们倾向于解释这一点   作为一个崩溃。如果某些内容阻止您的应用运行   打算,你需要告诉用户有关情况并解释一下   他们可以做到这一点。

答案 13 :(得分:2)

除了以上所述,好的,我只是想补充一下,想一想清理你的记忆。

应用程序退出后,iPhone OS将自动清除应用程序遗留的任何内容,因此手动释放所有内存只会增加应用程序退出所需的时间。

答案 14 :(得分:2)

- (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);
  }
}

答案 15 :(得分:2)

嗯,如果您的应用需要互联网连接,您可能'必须'退出该应用程序。您可以显示警告,然后执行以下操作:

if ([[UIApplication sharedApplication] respondsToSelector:@selector(terminate)]) {
    [[UIApplication sharedApplication] performSelector:@selector(terminate)];
} else {
    kill(getpid(), SIGINT); 
}

答案 16 :(得分:1)

[[UIApplication sharedApplication] terminateWithSuccess];

工作正常并自动调用

- (void)applicationWillTerminateUIApplication *)application delegate.

删除编译时警告添加此代码

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

答案 17 :(得分:1)

我使用上面提到的[[NSMutableArray new] addObject:nil]方法强制退出(崩溃)应用程序而不进行告诉退出(0)函数调用。

为什么呢?因为我的应用程序在所有网络API调用上使用证书固定来防止中间人攻击。这些包括我的财务应用在启动时进行的初始化调用。

如果证书身份验证失败,我的所有初始化调用都会出错,并使我的应用程序处于不确定状态。让用户回家然后回到应用程序并不会有帮助,因为除非应用程序已经被操作系统清除,否则它仍然没有初始化且不值得信任。

因此,在这种情况下,我们认为最好弹出一个警报,通知用户该应用程序在不安全的环境中运行,然后,当他们点击"关闭"时,强制退出应用程序上述方法。

答案 18 :(得分:0)

用户应决定何时退出应用。 当应用程序退出时,我不认为这是一个很好的用户交互。因此,它没有很好的API,只有主页按钮有一个。

如果出现错误:更好地实施或通知用户。 如果必须重新启动:更好地实现它通知用户。

这听起来很愚蠢,但是在不让用户决定而不通知他的情况下退出应用程序是不好的做法。 Apple表示,由于用户交互有一个主页按钮,因此相同功能(退出应用程序)不应该有两件事。

答案 19 :(得分:0)

退出应用程序,而不是主页按钮非iOS风格方法。

我做了这个帮手,但没有使用私人的东西:

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

但在我的情况下仍然不适合生产。它用于测试崩溃报告,或在核心数据重置后快速重启。如果函数留在生产代码中,那么只要安全不被拒绝。

答案 20 :(得分: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.
    }
}

当然,根据引用http://developer.apple.com/iphone/library/qa/qa2008/qa1561.html

的其他答案,使用exit(0)永远不适合在前台运行的普通制作应用。

答案 21 :(得分:0)

Swift 4.2(或更早版本)

可以使用名为Darvin的库。

import Darwin

exit(0) // Here you go

注意:iOS应用程序中不建议这样做。

这样做会导致崩溃日志。

答案 22 :(得分:0)

您不应直接调用函数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()
     }
}

答案 23 :(得分:0)

在iPadOS 13中,您现在可以像这样关闭所有场景会话:

for session in UIApplication.shared.openSessions {
    UIApplication.shared.requestSceneSessionDestruction(session, options: nil, errorHandler: nil)
}

这将调用您的应用程序委托上的applicationWillTerminate(_ application: UIApplication),并最终终止该应用程序。

但是要注意两件事:

有关iOS / iPadOS 13中场景的更多信息:https://developer.apple.com/documentation/uikit/app_and_environment/scenes

答案 24 :(得分:-1)

以其他方式退出应用

我做了这个帮手,但没有使用私人的东西:

退出(0);