4

我正在编写一个使用 GCD 计时器源的 Objective-C 包装器。目标之一是让包装器在应用程序进入后台时管理暂停计时器源。

文档表明它应该用于-[UIApplicationDelegate applicationDidEnterBackground:]使计时器无效等;我对此的解释有些松散(也许这是我的问题的根源?),因为我正在暂停 GCD 计时器(dispatch_suspend())以响应UIApplicationDidEnterBackgroundNotification)。

当包装器的实例被初始化时,它会检查[UIApplication sharedApplication].applicationState != UIApplicationStateBackground以确定 GCD 计时器源是否应该作为初始化序列的一部分最初恢复。它还注册UIApplicationDidEnterBackgroundNotificationUIApplicationWillEnterForegroundNotification用于暂停和恢复定时器源(分别)。

我观察到的问题是,似乎在某些情况下[UIApplication sharedApplication].applicationState != UIApplicationStateBackground通过了初始化期间的检查,以便恢复计时器源,并且收到的下一个通知是UIApplicationWillEnterForegroundNotification导致计时器源第二次恢复的情况。这会导致崩溃,因为计时器在第二次恢复时没有暂停。

我可以通过在本地跟踪应用程序状态并确认可能重复的转换来解决此问题,但我担心我可能做错了什么或可能存在错误(在实现中或在文档中)。

4

3 回答 3

2

这是应用程序状态的工作方式:

在初始启动时,

  1. 应用程序:didFinishLaunchingWithOptions
  2. applicationDidBecomeActive

当你按下主页按钮时,

  1. applicationWillResignActive
  2. applicationDidEnterBackground

当您打开后台应用程序时,

  1. applicationWillEnterForeground
  2. applicationDidBecomeActive

打开 - (初始启动和打开后台应用程序) - 调用 applicationDidBecomeActive - 在此处初始化计时器。

隐藏或接听电话等 - applicationWillResignActive 被调用 - 在这里停止计时器。

希望这可以帮助。

于 2012-12-17T07:48:18.623 回答
0

因此,您可以采取以下措施更好地了解正在发生的事情:

在您的应用程序 main.m 中,添加以下内容:

 @interface GTTestObject : NSObject

 - (void)logNotification:(id)sender;
 @end

 @implementation GTTestObject

 - (void)logNotification:(id)sender {

     NSLog(@"%@", [(NSNotification *)sender name]);

 }
 @end


 int main(int argc, char *argv[])
 {
     @autoreleasepool {

         // I'm assuming you'd be using ARC...
         GTTestObject *obj = [[GTTestObject alloc] init];
         [[NSNotificationCenter defaultCenter] addObserver:obj selector:@selector(logNotification:) name:nil object:nil];

         return UIApplicationMain(argc, argv, nil, NSStringFromClass([GTAppDelegate class]));
     }
 }

然后对于每个MyAppDelegate.m方法“...didFinishLaunching、...didEnterBackground 等” 添加这个:

     NSLog(@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd));

现在您将能够看到顺序、时间戳和(可能)与同时发生的通知/委托调用的任何冲突。

您可能会在不同的测试中得到稍微不同的结果,因此请多次运行以确保。

对于示例运行,我每次都看到:

 2012-12-21 08:13:58.559 Gamerton[34158:c07] [GTAppDelegate application:didFinishLaunchingWithOptions:] state: UIApplicationStateInactive
 2012-12-21 08:13:58.560 Gamerton[34158:c07] UIApplicationDidFinishLaunchingNotification state: UIApplicationStateInactive

 ...

 2012-12-21 08:13:58.561 Gamerton[34158:c07] [GTAppDelegate applicationDidBecomeActive:] state: UIApplicationStateActive
 2012-12-21 08:13:58.561 Gamerton[34158:c07] UIApplicationDidBecomeActiveNotification state: UIApplicationStateActive

 ... Hit home button

 2012-12-21 08:16:08.227 Gamerton[34170:c07] [GTAppDelegate applicationWillResignActive:] state: UIApplicationStateActive
 2012-12-21 08:16:08.228 Gamerton[34170:c07] UIApplicationWillResignActiveNotification state: UIApplicationStateActive
 2012-12-21 08:16:08.229 Gamerton[34170:c07] UIApplicationSuspendedNotification state: UIApplicationStateBackground
 2012-12-21 08:16:08.229 Gamerton[34170:c07] [GTAppDelegate applicationDidEnterBackground:] state: UIApplicationStateBackground

 ... Reopen app

 2012-12-21 08:16:59.364 Gamerton[34170:c07] [GTAppDelegate applicationWillEnterForeground:] state: UIApplicationStateBackground
 2012-12-21 08:16:59.365 Gamerton[34170:c07] UIApplicationWillEnterForegroundNotification state: UIApplicationStateBackground
 2012-12-21 08:16:59.365 Gamerton[34170:c07] _UIApplicationDidRemoveDeactivationReasonNotification
 2012-12-21 08:16:59.366 Gamerton[34170:c07] [GTAppDelegate applicationDidBecomeActive:] state: UIApplicationStateActive
 2012-12-21 08:16:59.366 Gamerton[34170:c07] UIApplicationDidBecomeActiveNotification state: UIApplicationStateActive
 2012-12-21 08:16:59.366 Gamerton[34170:c07] UIApplicationResumedNotification state: UIApplicationStateActive
 2012-12-21 08:16:08.230 Gamerton[34170:c07] UIApplicationDidEnterBackgroundNotification state: UIApplicationStateActive
于 2012-12-21T16:19:01.467 回答
0

从 UIApplication 文档:

UIApplicationStateInactive
The application is running in the foreground but is not receiving events. 
This might happen as a result of an interruption or because the application
is transitioning to or from the background.

因此,您的应用可能处于后台,很快将处于前台,但目前正在转换。

于 2012-12-06T22:07:47.400 回答