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

292

我正在编写一个iPhone应用程序,并且需要由于某些用户操作强制退出它。在清理了应用程序分配的内存后,调用哪种适当的方法来终止应用程序?

答案:

在清理了应用程序分配的内存之后,可以使用exit(0)方法来终止应用程序。


35
唯一正确的方式是——使用主页按钮。 - beryllium
5
我能想象到唯一一个可能会让人考虑以编程方式退出的情况是以下场景:应用程序启动,显示使用条款,拒绝接受后退出应用程序。这是一些品牌有时会向开发者施加压力要求做的事情。但这是错误的。 - Daniel
6
通常情况下,当您上传应用程序时,您需要在iTunes Connect上放置免责声明/使用条款(EULA)。如果用户下载您的应用程序,则意味着他们已接受您的EULA。 - Paul de Lange
9
有完全合理的原因需要强制退出iOS应用程序。我的情况是,我正在分发预发布的beta版本应用程序。beta版本开放了所有IAP免费使用,但这些功能有时间限制,需要在几周后过期。因此,我使用下面的方法在beta期结束后终止应用程序。我会在LIVE版本中删除这个功能。但是这个方法对我很有帮助,而且是正确的! - badweasel
6
如果一个应用是长时间后台运行的,且进入不再需要在后台运行的状态,这是退出应用的一个有效理由。例如,用户注销登录。这种情况下退出应用程序是有意义的,因为当下次启动应用程序时,它将开始一个干净的状态。这将作为一种安全措施,防止内存泄漏等问题发生。请注意,在这种情况下,应用程序将会退出“后台”,因此用户不会察觉到任何问题。 - frankodwyer
显示剩余4条评论
24个回答

276

在 iPhone 上,没有退出应用程序的概念。唯一会导致应用程序退出的操作是触摸手机上的 Home 按钮,而开发人员无法访问该按钮。

据苹果公司称,您的应用程序不应自行终止。由于用户没有按 Home 按钮,任何回到主屏幕都会给用户留下您的应用程序崩溃了的印象。这种令人困惑、非标准的行为应该被避免。


13
正如我之前所说的,这是非标准行为,应该避免使用。 iPhone 应用程序不是桌面应用程序,不要将它们视为同等。 - August
8
我理解苹果公司的观点,但我也有类似的情况。我的应用需要网络访问,如果没有网络,用户应该能够退出应用而非只是收到错误提示信息。 - Anthony Main
25
我们有帮助人们入睡的应用程序。他们希望在一定时间后终止应用程序,以减少电池耗电量。我认为这种情况是可接受的 - 因为用户希望已经进入睡眠状态,无法手动退出应用程序。 - JamesSugrue
39
我仍然不同意。当他们醒来时,应用程序“消失”了,让用户感到困惑。相反,在您的应用程序中设置一个定时器,然后在时间到达后将应用程序置于空闲状态--没有活动。一个完全不做任何事情的应用程序不会耗尽电池。Springboard也是一个应用程序--它不会关闭以节省能源。相反,它只是等待用户输入。 - August
9
这并不是真正回答问题。它的准确性为100%,但我认为最好是将其作为对提问者或被采纳答案的评论。 - Ben Zotto
显示剩余16条评论

226

你尝试过使用 exit(0) 吗?

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


85
由于这样做是违反苹果规定的(可能会导致您的应用程序因非标准界面而在应用商店中被拒绝),因此请把August的回答视为“正确的回答”。顺便提一下,Brett的回答对于所有C程序都是正确的,而NSThread适用于所有Cocoa程序。 - Olie
22
在技术问答QA1561中,苹果强烈反对使用"exit"命令,因为它会让应用程序看起来像是已经崩溃了。参考链接:http://developer.apple.com/iphone/library/qa/qa2008/qa1561.html - progrmr
8
因为 exit 不是实例方法,所以调用 [[NSThread mainThread] exit] 会导致应用程序崩溃。在 iOS 4 中,调用 exit(0) 会将应用程序发送到后台。但是如果再次调用 exit(0),则会导致应用程序崩溃,至少在模拟器中是如此。 - user123444555621
14
我知道为什么有那么多人反对这个,但能不能给我们开发者一些信任呢?我们都是成年人,想了解这个功能。我觉得它对内部的质量保证构建非常有用,当我第一次搜索它时,看到这个“错误”的答案,我很高兴。 - evanflash
12
“不要那样做”从来不是正确的回答。如果你愿意,可以发出警告和免责声明,但唯一正确的回答是“这是如何做的”。如果我正在寻找如何做某事(也许我想在调试时强制退出),那些正义地宣称“你不能这样做!”并试图掩盖我需要的答案的人会浪费我的时间。无论有多少人因为错误的原因而要做某件事情,正确的StackOverflow回答都是回答问题的那个,因为有好原因的人也会通过搜索找到这个答案。 - Glenn Maynard
显示剩余17条评论

51

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

1
苹果会批准这个“exit(0)”吗?因为有些人说当你使用exit 0时,苹果会拒绝你的应用程序。 - Gajendra K Chauhan
2
@GajendraKChauhan exit(0)并不重要。重点是你的应用程序具有“退出行为”。除了由非常重要的第三方制作的一些应用程序之外,AppStore禁止退出行为本身。此外,模仿主页按钮行为也可能会被拒绝。 - eonil

41

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

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

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

在iOS中,用户按Home按钮关闭应用程序。如果您的应用程序在某些条件下无法提供其预期功能,则建议的方法是为用户显示一个提示,指示问题的性质和用户可以采取的可能行动 - 打开WiFi、启用位置服务等,并允许用户自行决定是否终止应用程序。

警告:不要调用exit函数。调用exit的应用程序将会出现崩溃,而不是执行优雅的终止并动画返回到主屏幕。

此外,由于调用exit,可能无法保存数据,因为-applicationWillTerminate:和类似的UIApplicationDelegate方法将不会被调用。

如果在开发或测试期间需要终止应用程序,则建议使用abort函数或assert宏。


2
刚刚添加了一个没有按钮的AlertView以满足要求。很容易。 - Schultz9999
很棒的答案,我只是使用了exit(0),并不知道它属于私有API。 - Alex Cio

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

2
至少在模拟器上,如果您这样做,当用户重新打开应用程序时,警报仍将存在。因此,我建议给他们至少一个按钮。 - cheshirekow
使用Kalyan的答案,以便在按下主页按钮时应用程序退出。 - Timur Kuchkarov
问题在于它实际上并没有退出应用程序,因此除非用户关闭应用程序,否则开发人员想要通过退出来完成的任何操作(例如丢弃无效/旧UI,清除常量等等)都不会执行。 - Ky -
这不会关闭应用程序。 - Dustin

37

进入您的info.plist文件,检查“应用程序不在后台运行”这个键。这样,当用户点击主屏幕按钮时,应用程序会完全退出。


1
但后台进程也会被解除。 - Gajendra K Chauhan

17
application-info.plist中添加UIApplicationExitsOnSuspend属性,并将其设置为true

这个设置能在运行时更改吗?我的意思是,我想要在后台运行,除非我的应用程序选择在下一次挂起时退出 - 在那个时候,我将想要引入UIApplicationExitsOnSuspend。这可能吗? - Motti Shneor

13
经过一些测试,我能够得出以下结论:
  • 使用私有接口[UIApplication sharedApplication]会导致应用程序看起来像是崩溃了,但它会在这样做之前调用- (void)applicationWillTerminate:(UIApplication *)application;
  • 使用exit(0);也会终止应用程序,但它看起来很“正常”(SpringBoard的图标以预期的方式显示,并带有缩放效果),但不会调用- (void)applicationWillTerminate:(UIApplication *)application委托方法。
我的建议:
  1. 手动调用委托中的- (void)applicationWillTerminate:(UIApplication *)application方法。
  2. 调用exit(0);

苹果公司表示不要使用exit函数,因为“调用exit函数的应用程序会让用户感觉崩溃了,而不是优雅的终止并回到主屏幕”。详见https://developer.apple.com/library/ios/#qa/qa2008/qa1561.html。 - user585968

9

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

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

当我收到此通知时,我只需拨打电话。
        exit(0);

它是执行所有工作的程序。最好的事情是用户想要退出,这就是为什么在那里调用它不应该成为一个问题。

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

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


1
这不是一个好的解决方案,因为应用程序会因其他原因而失去活动状态,例如来电。 - frankodwyer
解决方案是添加一个检查,只有在必要时才退出。例如,如果用户在启动屏幕上,则即使电话来了也没关系。自iOS 2以来,我的应用程序中苹果从未拒绝过这个解决方案。https://dev59.com/jm855IYBdhLWcg3wViy3#43906936 - cat

6
最近我的应用被拒绝了,因为我使用了一个未经记录的方法。字面意思是:
“不幸的是,它无法添加到App Store,因为它使用了私有API。在iPhone开发者计划许可协议3.3.1节中规定,禁止使用非公共API:”
“3.3.1 应用程序只能按照苹果公司规定的方式使用记录的API,并且不得使用或调用任何私有API。”
您的应用程序中包含的非公共API是terminateWithSuccess。”

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接