applicationWillTerminate 何时调用,何时不调用
Posted
技术标签:
【中文标题】applicationWillTerminate 何时调用,何时不调用【英文标题】:applicationWillTerminate when is it called and when not 【发布时间】:2011-10-19 07:42:29 【问题描述】:您好,我已阅读关于 SO 的几个关于 applicationWillTerminate 被调用而不被调用的问题。
我想总结一下我的理解,因为有几篇文章的说法不同。
对于 ios(没有多任务处理),它总是在按下主页按钮时调用。
适用于 IOS 4 及更高版本
一个。它在按下主页按钮时不被调用(当应用移至后台时)
b.从多任务坞站关闭应用程序时调用它,并且如果应用程序在 info.plist 中禁用了突然终止标志,否则不会调用它。 (我设置了“应用程序应该获取 App Died 事件”,即使在从多任务坞站关闭应用程序时,也没有调用终止函数)
基于此,我有几个问题
设置应用程序应该获得 App Died 事件标志是一个好习惯吗? (我设置了“应用程序应该获取 App Died 事件”,即使在从多任务坞站关闭应用程序时,也没有调用终止函数)
或
注册“UIApplicationWillTerminateNotification”是否比 info.plist 设置更好?
基本上我只需要在应用程序终止时才需要做一些工作,而不是在它移动到后台时。
或
编辑(1): 当应用程序终止时,以下内容将发送到 APP。怎么抓?
程序收到信号:“SIGKILL”。
编辑(2):
请注意:从多任务坞站中移除时,它不会在 IOS 4 及更高版本中被调用。你可能认为是。但在我的情况下不是。
请问有人知道为什么吗?还有什么我想念的吗。
还请注意,我设置了“应用程序应该获取 App Died 事件”,即使这样它也没有被调用。
编辑(3):
以下问题的答案也无效。 applicationWillTerminate does not get invoked
有人和我有同样的问题吗?
【问题讨论】:
我也有同样的问题。备注:您无法捕获 SIGKILL,此信号由操作系统处理,相当于删除所有应用资源(因此您的应用无法捕获此信号)。 谢谢。所以我们回到寻找如何在IOS 4及更高版本中制作“applicationWillTerminate”。 【参考方案1】:简而言之,除非您将 Info.plist 中的 UIApplicationExitsOnSuspend
设置为 YES,否则在 iOS4 及更高版本中,无法保证 applicationWillTerminate:
将被调用。
正如the documentation 所说:
对于支持后台执行的应用,这个方法是 通常不会在用户退出应用程序时调用,因为 在这种情况下,应用程序只是移动到后台。然而,这 方法可能在应用程序运行的情况下被调用 后台(未挂起)和系统需要终止它 出于某种原因
(强调我的。)
如果您需要在应用退出之前执行某些操作,您需要在 applicationDidEnterBackground:
中执行此操作。没有办法捕捉到 SIGKILL。
【讨论】:
看起来无法预测是否调用了 applicationWillTerminate。 文档说..但是当我从多任务坞站关闭它时,该函数不会被调用!顺便说一句,我在后台运行音频,并在用户停止音频或关闭应用程序时使用一些信息更新服务器。这就是为什么我不能使用 applicationDidEnterBackground: 当你从多任务扩展坞关闭它时,它在哪里说它会被调用?它说的正是相反。它说它通常不被调用。 我用另一种方式解释了“可能”……很公平。我想那时我将无法完成我打算做的房屋清洁功能。这有点奇怪不是吗? 感谢您指出“除非您的 Info.plist 中的 UIApplicationExitsOnSuspend 设置为 YES”。这就是终止我的应用程序的原因。不知道该设置是如何放在那里的,但感谢您指出。【参考方案2】:我看到-applicationWillTerminate:
被以下测试调用。在一个新项目中(我使用了“单一视图应用程序”模板),将以下内容添加到 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 5.1 和 6.1(均为 iPhone)的 iOS 模拟器中进行了尝试,并在两种情况下都看到了这种情况。我还在运行 iOS 6.1.2 的 iPhone 4S 上进行了测试,并看到了相同的行为。
【讨论】:
我也认识到这不是对何时调用-applicationWillTerminate:
的明确描述,也不能保证是全面的。尽管如此,我发现即使在支持后台执行的应用程序中也可以调用它,这很有用。
如果您删除了-applicationDidEnterBackground:
,则不会调用-applicationWillTerminate:
(在iOS 7.1 上测试过)。这是有道理的——运行后台任务的应用程序可以使用...willTerminate:
消息来结束其后台任务;没有此类任务的应用不需要这样做。
大多数情况下,-[UIApplication applicationWillTerminate:]永远不会被调用,除非应用程序被iOS系统终止(比如内存不够)。所以当用户崩溃或杀死时,它不会被调用。
如果您在应用程序在前台工作时直接双击主页按钮并在App Switcher中向上滑动并杀死应用程序,无论是否有后台任务都会调用applicationWillTerminate:
。但是,如果你只点击一次 Home 键,并且先让应用程序进入后台,然后双击 Home 键,稍后向上滑动并杀死应用程序,则只有在后台进程正在进行时才会调用 applicationWillTerminate:
。否则不会被调用。
@erkanyildiz 我看到对于 iPhone X,即使在前台杀死应用程序,该方法仍然没有被调用。【参考方案3】:
据我所知,您的应用程序会在 3 种情况下死掉。
被最终用户终止,你可以在-[UIApplication applicationWillEnterBackground:]
做一些事情,在这种情况下,-[UIApplication applicationWillTerminate:]
不会被调用。
被系统丢弃,比如内存不够,可以在-[UIApplication applicationWillTerminate:]
做点什么,此时不知道applicationWillEnterBackground:
是否被调用过;
崩溃了,只能使用某种崩溃报告工具。 (编辑:捕捉SIGKILL
是不可能的)
【讨论】:
applicationWillTerminate 在用户终止应用程序时被调用 @BaSha,您对 Xcode 9 和 iOS 11 是正确的。但是,正如我回答这个问题时所说的那样。 @BaSha 不,不是。只有某些时候。文档清楚地表明这不能可靠地使用。 applicationWillTerminate 在用户终止应用程序时被调用。但是当第一个应用程序进入后台状态按下主页按钮然后用户终止应用程序时它不会被调用。【参考方案4】:来源:http://www.cocos2d-iphone.org/forum/topic/7386
我将状态保存代码从 applicationWillTerminate 复制到 applicationDidEnterBackground 并添加了 multitaskingEnabled 布尔值,以便我只在 applicationDidEnterBackground 中调用状态保存。因为,在多任务设备上有一个调用 applicationWillTerminate 的实例:如果应用程序在前台并且您关闭了设备。在这种情况下,applicationDidEnterBackground 和 applicationWillTerminate 都会被调用。
【讨论】:
是的 .. 现在你有另一种方式来了解它吗? 不,但是这个 SO 答案解释了同样的事情 - 并引用了支持它的苹果文档说明:***.com/a/13728148/1244184【参考方案5】:我们知道,当调用-applicationWillTerminate
时,应用程序只有 5 秒。所以如果有人想在那个时候更新服务器。比使用
同步调用。
[NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&error];
注意:- -applicationWillTerminate
不会在应用程序从挂起状态被终止时调用。暂停状态意味着应用程序在 backgroupd 中没有任何工作。解决方案之一是使用后台任务。
【讨论】:
如何在swift中使用?【参考方案6】:基于Andrew's test,我理解applicationWillTerminate(_:) 的文档有以下说明:
对于不支持后台执行或链接到 iOS 3.x 或更早版本的应用程序,当用户退出应用程序时始终调用此方法。对于支持后台执行的应用程序,通常不会在用户退出应用程序时调用此方法[立即],因为在这种情况下应用程序只是移动到后台。但是,在应用程序在后台运行(未挂起)并且系统出于某种原因需要终止它的情况下,可能会调用此方法[而不是beginBackgroundTask(expirationHandler:)]。
【讨论】:
【参考方案7】:// 绝对答案 applicationWillTerminate
func applicationWillTerminate(application: UIApplication)
print("applicatoinWillTerminate")
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
第一步:command + shift + h(双击(tab))
第 2 步:移动应用顶部(杀死)
第 3 步:applicationWillTerminate 工作
【讨论】:
它没有被称为 willterminate .. 永远不要进入这个函数 .. 如何修复? 这对我有用,但前提是应用程序从运行到终止。具体来说,如果用户当前正在使用应用程序,则调用“applicationWillTerminate”,然后双击主页以终止应用程序。如果用户先点击home,应用进入后台,刷出应用不会调用“applicationWillTerminate”。 我们无法确定应用程序是否会进入该将终止的方法,我注意到我的将终止方法的代码仅在我进行调试时执行,并且该函数有一个断点。以上是关于applicationWillTerminate 何时调用,何时不调用的主要内容,如果未能解决你的问题,请参考以下文章
“applicationWillTerminate”没有被迅速调用
applicationWillTerminate 何时调用,何时不调用
Swift - 在 applicationWillTerminate 中调用本地通知方法
为啥 UIWebView 不在我的应用程序委托中的 applicationWillTerminate: 处加载 NSURLRequest?