【问题标题】:applicationWillEnterForeground vs. applicationDidBecomeActive, applicationWillResignActive vs. applicationDidEnterBackgroundapplicationWillEnterForeground 与 applicationDidBecomeActive、applicationWillResignActive 与 applicationDidEnterBackground
【发布时间】:2011-04-12 09:30:01
【问题描述】:

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

applicationWillEnterForeground vs applicationDidBecomeActive -- 有什么区别?

当应用程序进入休眠状态并且您希望它准备好清理和保存数据时,哪个是合适的委托?

applicationWillResignActive 与 applicationDidEnterBackground 有什么区别?

另外,我注意到 applicationWillResignActive 在收到短信或来电时被调用,但用户选择单击“确定”并继续。我不希望我的应用在这些情况下采取任何行动。我只是希望它在没有任何中间清理的情况下继续运行,因为用户没有退出应用程序。所以,我认为只在 applicationDidEnterBackground 中进行清理工作更有意义。

非常感谢您对最佳实践的意见,以选择实施哪些代表以实现唤醒和睡眠,以及考虑诸如被短信/电话打断等事件。

谢谢

【问题讨论】:

    标签: ios objective-c iphone uiapplicationdelegate


    【解决方案1】:

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

    - (void)sceneWillEnterForeground:(UIScene *)scene
    - (void)sceneDidBecomeActive:(UIScene *)scene
    

    【讨论】:

      【解决方案2】:

      Managing Your App's Life Cycle 对您的问题很有帮助。对于快速概念,您可以查看该文档中的图形。 您还可以阅读 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 年。
      【解决方案3】:

      唤醒时,即重新启动应用程序(通过跳板、应用程序切换或 URL)applicationWillEnterForeground: 被调用。它只在应用程序可以使用时执行一次,在进入后台后,而 applicationDidBecomeActive: 在启动后可能会被多次调用。这使得 applicationWillEnterForeground: 非常适合需要在重新启动后进行一次的设置。

      applicationWillEnterForeground: 被调用:

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

      applicationDidBecomeActive: 被调用:

      • application:didFinishLaunchingWithOptions: 之后首次启动应用程序时
      • applicationWillEnterForeground: 之后,如果没有要处理的 URL。
      • 在调用application:handleOpenURL: 之后。
      • applicationWillResignActive: 之后,如果用户忽略了电话或短信等中断。

      applicationWillResignActive: 被调用:

      • 当有电话等中断时。
        • 如果用户接听电话applicationDidEnterBackground:
        • 如果用户忽略调用applicationDidBecomeActive:
      • 按下主页按钮或用户切换应用时。
      • 文档说你应该
        • 暂停正在进行的任务
        • 禁用计时器
        • 暂停游戏
        • 降低 OpenGL 帧速率

      applicationDidEnterBackground: 被调用:

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

      The official documentation.

      【讨论】:

      • 还有一点要补充。如果您从您的应用程序(双击主页按钮)打开后台应用程序列表,然后返回到它(选择您的应用程序的预览) - -applicationWillEnterForeground: 将不会被调用,只有 -applicationDidEnterBackground: (假设,iOS 不认为这是重新启动)。
      • @kpower 是的,这只是打破了我的脖子......从没想过 willEnterForeground 在这种情况下不会被调用......
      • 不是每次后台到前台都会调用applicationWillEnterForeground:吗?!我找不到事后没有applicationDidBecomeActive 的情况。
      • 这不准确。 applicationWillResignActive 可以在没有 applicationDidEnterBackground 的情况下调用
      【解决方案4】:

      applicationWillResignActive 在系统请求权限时被调用。 (在 iOS 10 中)。以防万一有人遇到和我一样的麻烦……

      【讨论】:

      【解决方案5】:

      applicationWillEnterForeground 被调用:

      当应用重新启动时(从后台到前台) 应用程序第一次启动时不会调用此方法,即调用 applicationDidFinishLaunch 时,但仅在来自后台时调用 applicationDidBecomeActive

      applicationDidBecomeActive 被调用

      didFinishLaunching 之后首次启动应用程序时 在applicationWillEnterForeground 之后,如果没有要处理的 URL。 在调用application:handleOpenURL: 之后。 在applicationWillResignActive 之后,如果用户忽略了电话或短信等中断。 应用程序中任何地方的 alertView 消失后

      【讨论】:

      • 你有没有机会知道这是否从 iOS 7 开始改变?我记得(我可能弄错了)在 applicationWillEnterForeground 中做一些事情(iOS 5/6)并在应用程序首次启动时运行。截至目前,在 7.1/8 中,您是对的 applicationWillEnterForeground 在启动时不会被调用。
      【解决方案6】:

      在 iOS 8+ 中,接电话有一个微妙但重要的区别。

      在 iOS 7 中,如果用户接听电话,则 applicationWillResignActive: 和 applicationDidEnterBackground: 都会被调用。但在 iOS 8+ 中,只有 applicationWillResignActive: 被调用。

      【讨论】:

        【解决方案7】:

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

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

        已完成发射

        已激活

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

        OnResignActivation


        已激活

        • 双击主页按钮列出不活动的应用,选择另一个应用,然后重新启动我们的应用:
        • 单按 Home 键,然后重新启动:
        • 锁定(开/关按钮),然后解锁:

        OnResignActivation

        DidEnterBackground


        WillEnterForeground

        已激活

        • 双击 Home 键,并终止我们的应用程序:(后续重新启动是第一种情况)

        OnResignActivation

        DidEnterBackground

        DidEnterBackground(仅限 iOS 7?)

        是的,DidEnterBackground 在 iOS7 设备上被调用了两次。两次 UIApplication 状态都是背景。但是,iOS 8 模拟器没有。这需要在 iOS 8 设备上进行测试。当我得到答案时,我会更新我的答案,或者其他人可以确认。

        【讨论】:

          猜你喜欢
          • 2014-11-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多