【问题标题】:applicationDidBecomeActive getting called twiceapplicationDidBecomeActive 被调用两次
【发布时间】:2012-05-05 11:53:06
【问题描述】:

第一次启动应用程序时,我的应用程序委托方法 applicationDidBecomeActive: 被调用了两次。我有一部分代码我只想执行一次并且我已经放入applicationDidBecomeActive:

我该怎么办?

【问题讨论】:

  • 在 applicationDidBecomeActive: 上设置断点时堆栈跟踪是什么样的?两个电话完全一样吗?如果不是(也不应该是),那么这应该会导致您遇到问题。

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


【解决方案1】:

我有问题。我正在使用定位服务。在我点击位置服务警报上的“确定”后第一次启动时,我的 applicationDidBecomeActive 会再次被调用一次,这是正常的 iOS 行为。

【讨论】:

  • 我的应用在每次激活时都需要身份验证。使用此位置警报,用户需要在警报弹出后立即输入密码。我需要避免这种情况发生。
  • @LocPham :我的建议是在应用程序委托实现文件中保留一个实例变量,并且每当调用 applicationDidBecomeActive 时递增。当此变量的值 > 1 时,不要执行您的登录警报代码。不要忘记重置它。此外,此建议纯粹是基于您的要求而没有看到您的代码。也可能是更好的方法。
【解决方案2】:

如果您只想在应用激活时调用您的代码一次,请尝试通过两种方法调用它。

  1. didFinishLaunchingWithOptions
  2. applicationWillEnterForeground

而不是只从applicationDidBecomeActive 调用它。

【讨论】:

    【解决方案3】:

    这是因为位置或推送通知警报。

    原生位置/推送通知被解除后,applicationDidBecomeActive 将被调用。

    【讨论】:

    • 我们如何正确区分“真正的”applicationDidBecomeActive:当我们的应用实际进入后台与由于位置警报而强制进入后台时?
    • 我的应用在每次激活时都需要身份验证。使用此位置警报,用户需要在警报弹出后立即输入密码。我需要避免这种情况发生。
    【解决方案4】:

    我不知道这是否会有所帮助,但我只是在一个完全简单的应用程序中遇到了同样的问题,它不使用定位服务,我发现这是一种错觉。查看我收到的日志消息:

    2012-12-22 10:47:45.329 Bizarro[10416:907] start applicationDidBecomeActive:
    2012-12-22 10:47:45.333 Bizarro[10416:907] end applicationDidBecomeActive:
    2012-12-22 10:47:45.329 Bizarro[10416:907] start applicationDidBecomeActive:
    2012-12-22 10:47:45.333 Bizarro[10416:907] end applicationDidBecomeActive:
    

    仔细观察。看看时代。第一条和第三条消息具有相同的时间。第二条和第四条消息的时间相同。它们是相同的消息!这是一个 Xcode 错误;它与我的代码无关。 Xcode 两次报告相同的日志消息。

    就我而言,我可以通过关闭所有运行行为 -> 生成输出来防止这种情况发生。

    【讨论】:

      【解决方案5】:

      怎么样:

      • 增加applicationDidBecomeActive
      • 减少权限请求的回调事件或在关闭时触发另一个applicationDidBecomeActive 的其他警报。

      【讨论】:

        【解决方案6】:

        在 Xcode 6 中出现这种情况的新原因是:当您在可调整大小的模拟器中启动应用程序时,applicationDidBecomeActive: 将被调用两次。

        它使用默认尺寸类启动应用程序,然后应用您上次使用的尺寸——即使您使用的是默认值。任何时候应用大小类的更改,applicationDidBecomeActive: 都会被调用。

        【讨论】:

          【解决方案7】:

          应用首次启动时 它按顺序调用,

          1. didFinishLaunchingWithOptions
          2. applicationDidBecomeActive两次

          当我们打开Control Center时,它只会调用,

          applicationDidBecomeActive
          

          当应用程序从后台转到前台时,它会按顺序调用

          1. applicationWillEnterForeground
          2. applicationDidBecomeActive

          【讨论】:

            【解决方案8】:

            我目前看到双重通知。

            发生这种情况是因为我的 AppDelegate 的初始化代码被调用了两次。
            它在main() 执行[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:application topLevelObjects:&tl] 时被调用一次(即加载.XIB 文件时),因为.XIB 文件正在为我的自定义AppDelegate 设置FirstResponder,然后在main() 调用时再次调用它[[myAppDelegate alloc] init].

            初始化代码是 addObserver 调用的代码,因此为我关心的每个通知设置了两个观察者,这就是我的通知被调用两次的原因。

            我是一个新手 OS X 程序员,所以我还不确定解决这两个问题的最佳方法,但想在这里发布它以防它对其他人有帮助,另一个地方可以查看。

            【讨论】:

              【解决方案9】:

              您是否可能在 Interface Builder 和 AppDelegate 代码中创建了您的类的实例?

              【讨论】:

              • 好检查做一个 NSLog(@"%x",(int)self);在那个委托中,确保它是同一个实例......
              • 即使是这种情况,应用程序对象本身也只能有一个委托,并且只会发送一次消息。
              • @Grady:指针有一个格式说明符:NSLog(@"%p", self);
              • 哦,你是对的:我看错了。我假设某个对象(不是 AppDelegate)收到了两次消息。我曾经使用具有相同awakeFromNibinit 方法的类(在测试期间!:))。我的回答与问题完全无关,我会在几秒钟后将其删除。
              • 感谢 Iulius Cæsar...我认为我的大脑中有一个格式说明符大小的洞,那个洞会滑过...
              【解决方案10】:

              如果您的代码只希望在应用启动时调用一次,请使用

              - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
              

              改为。

              否则,每当您的应用再次处于活动状态时,都会调用 applicationDidBecomeActive,因此这不仅意味着您的情况是两次,而是每次用户在切换到另一个应用后切换回您的应用时。

              【讨论】:

              • 在应用程序之间切换没问题。我也想在那个时候执行代码。但在第一次启动时,它被调用了两次。
              【解决方案11】:

              如果你使用 RxSwift,那么你可以限制应用程序事件,所以它不会在同一秒内调用两次:

              NotificationCenter.default.rx.notification(Notification.Name.UIApplicationDidBecomeActive)
                      .throttle(1, scheduler: MainScheduler.instance)
                      .subscribe { (event) in
                          self.appEnteredFromBackground()
                      }.disposed(by: disposeBag)
              
              private func appEnteredFromBackground() {
                      Analytics.trackPageView(withScreen: .home)
                      dataStore.checkIfAllowingRides()
                  }
              

              我将此代码放在我的实际视图控制器中,逻辑应该发生在 ApplicationDidBecomeActive 上。

              【讨论】:

                【解决方案12】:

                我只是在applicationDidBecomeActive: 顶部检查请求是否真的发送(我为此创建了一个函数,检查状态),如果是,我已经返回。 第二次在applicationDidBecomeActive: 中,函数读取状态为拒绝或允许,因为这是在用户回答警报之后。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2016-04-01
                  • 2017-01-19
                  • 2014-02-04
                  • 2016-12-13
                  • 2016-01-30
                  • 2015-12-20
                  • 2019-04-04
                  • 2016-02-25
                  相关资源
                  最近更新 更多