applicationWillEnterForeground与applicationDidBecomeActive,applicationWillResignActive与applicationDidEnterBackground


215

当应用程序从后台唤醒并且您希望它准备好处于活动状态时,哪个合适的委托实现?

applicationWillEnterForeground与applicationDidBecomeActive-有什么区别?

当应用程序要进入睡眠状态并且您想为其准备清理和保存数据时,哪个合适的委托实现?

applicationWillResignActive与applicationDidEnterBackground-有什么区别?

另外,我注意到当传入的SMS或呼叫进入时,会调用applicationWillResignActive,但是用户选择单击“确定”并继续。我不希望我的应用在这些情况下采取任何措施。我只希望它保持运行而无需任何中间清理,因为用户没有退出该应用程序。因此,我认为仅在applicationDidEnterBackground中进行清理工作更有意义。

非常感谢您对最佳做法的投入,以便选择实施哪些代表来唤醒和入睡以及考虑诸如被SMS /呼叫打断等事件。

谢谢

Answers:


449

唤醒时即重新启动应用程序(通过跳板,应用程序切换或URL)applicationWillEnterForeground:。在应用程序准备就绪后,仅在后台运行后才执行一次,而applicationDidBecomeActive:在启动后可能会多次调用。这applicationWillEnterForeground:对于重新启动后只需进行一次设置的理想选择。

applicationWillEnterForeground: 叫做:

  • 重新启动应用程序时
  • 之前 applicationDidBecomeActive:

applicationDidBecomeActive: 叫做:

  • 应用首次启动后的时间 application:didFinishLaunchingWithOptions:
  • applicationWillEnterForeground:如果没有URL处理。
  • 之后application:handleOpenURL:被称为。
  • 之后applicationWillResignActive:,如果用户忽略中断就像一个电话或短信。

applicationWillResignActive: 叫做:

  • 当有电话之类的干扰时。
    • 如果用户接听电话applicationDidEnterBackground:被呼叫。
    • 如果用户忽略呼叫applicationDidBecomeActive:被调用。
  • 当按下主屏幕按钮或用户切换应用程序时。
  • 文档说你应该
    • 暂停正在进行的任务
    • 禁用计时器
    • 暂停游戏
    • 降低OpenGL帧率

applicationDidEnterBackground: 叫做:

  • applicationWillResignActive:
  • 文档说您应该:
    • 释放共享资源
    • 保存用户数据
    • 使计时器无效
    • 保存应用程序状态,以便在应用程序终止时可以将其恢复。
    • 禁用UI更新
  • 您有5秒的时间做您需要做的事情并返回方法
    • 如果您未在约5秒钟内返回,则该应用程序将终止。
    • 您可以要求更多时间 beginBackgroundTaskWithExpirationHandler:

官方文档。


10
再增加一件事。如果您从应用程序中打开后台应用程序列表(双击主屏幕按钮),然后返回到该列表(选择应用程序的预览),-applicationWillEnterForeground:则不会被调用,只会-applicationDidEnterBackground:(假设iOS不会认为它是重新启动)。
kpower

@kpower是的,那简直让我伤透了脖子……从未想到在这种情况下将不会调用
willEnterForeground

是不是applicationWillEnterForeground:每次从背景到前景都会被调用?!我找不到applicationDidBecomeActive以后不调用WITHOUT的情况。
Desmond DAI

这是不正确的。在没有applicationDidEnterBackground的情况下,可以调用applicationWillResignActive
MichaelGofron

27

管理应用程序的生命周期有助于解决您的问题。有关快速概念,请参见该文档中的图。您还可以从XCode向导生成的代码中读取注释。列出如下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    /*
     Sent when the application is about to move from active to inactive state. 
     This can occur for certain types of temporary interruptions (such as an 
     incoming phone call or SMS message) or when the user quits the application 
     and it begins the transition to the background state.
     Use this method to pause ongoing tasks, disable timers, and throttle down 
     OpenGL ES frame rates. Games should use this method to pause the game.
     */
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    /*
     Use this method to release shared resources, save user data, invalidate 
     timers, and store enough application state information to restore your 
     application to its current state in case it is terminated later. 
     If your application supports background execution, this method is called 
     instead of applicationWillTerminate: when the user quits.
     */
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    /*
     Called as part of the transition from the background to the active state; 
     here you can undo many of the changes made on entering the background.
     */
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    /*
     Restart any tasks that were paused (or not yet started) while the 
     application was inactive. If the application was previously in the 
     background, optionally refresh the user interface.
     */
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    /*
     Called when the application is about to terminate.
     Save data if appropriate.
     See also applicationDidEnterBackground:.
     */
}

有关更多详细说明,请参阅UIApplicationDelegate的官方文档。


链接已死。
菲利普·博斯曼

修订一些描述和链接,2019年。
tomjpsun

13

我对Dano的回答仍然有些困惑,因此我做了一些测试以获取某些情况下的事件流以供参考,但是它对您也可能有用。这适用UIApplicationExitsOnSuspend于不在info.plist中使用的应用。这是在iOS 8模拟器上进行的,并已通过iOS 7设备确认。请原谅Xamarin的事件处理程序名称。它们非常相似。

  • 从非运行状态的初始启动和所有后续启动:

完成启动

激活

  • 中断(电话,顶部向下滑动,底部向上滑动):
  • 主页按钮双击列出不活动的应用程序,然后重新选择我们的应用程序:

OnResignActivation


激活

  • 主页按钮连按两次列出不活动的应用程序,选择另一个应用程序,然后重新启动我们的应用程序:
  • 按下主页按钮,然后重新启动:
  • 锁定(开/关按钮),然后解锁:

OnResignActivation

DidEnterBackground


将进入前台

激活

  • 双击主屏幕按钮,然后终止我们的应用程序:(随后的重新启动是第一种情况)

OnResignActivation

DidEnterBackground

DidEnterBackground(仅适用于iOS 7?)

是的,DidEnterBackground在iOS7设备上被两次调用。两次UIApplication状态均为Background。但是,iOS 8模拟器没有。这需要在iOS 8设备上进行测试。当我得到答案时,我将更新我的答案,否则其他人可以确认。


9

applicationWillEnterForeground 叫做:

重新启动应用程序时(从后台到前台)首次启动应用程序(即,何时调用)时不调用此方法applicationDidFinishLaunch,仅当来自后台 程序时才调用此方法applicationDidBecomeActive

applicationDidBecomeActive 叫做

如果没有要处理的网址,则在didFinishLaunching 之后首次启动应用程序时applicationWillEnterForeground。之后application:handleOpenURL:被称为。之后applicationWillResignActive,如果用户忽略中断就像一个电话或短信。从应用程序的任何地方消失了alertView之后


您是否偶然知道自iOS 7起它是否已更改?我记得(我可能会误会)在applicationWillEnterForeground中进行操作(iOS 5/6)并在应用程序首次启动时运行该操作。到目前为止,在7.1 / 8中,您是正确的applicationWillEnterForeground不会在启动时被调用。
Jinyoung Kim


5

在iOS 8+中,拨打电话存在细微但重要的区别。

在iOS 7中,如果用户拨打电话,则会同时调用applicationWillResignActive:和applicationDidEnterBackground:。但是在iOS 8+中,仅调用applicationWillResignActive:。


1

对于iOS 13+,将执行以下方法:

- (void)sceneWillEnterForeground:(UIScene *)scene
- (void)sceneDidBecomeActive:(UIScene *)scene
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.