我正在编写一个使用GCD计时器源的Objective-C包装器。其中一个目标是包装器在应用程序进入后台时管理暂停计时器源。
-[UIApplicationDelegate applicationDidEnterBackground:]
的{{3}}表示它应该用于使计时器无效,等等;我稍微松散地解释了这个问题(也许这是我问题的根源?)因为我暂停了GCD计时器(dispatch_suspend()
)以响应UIApplicationDidEnterBackgroundNotification
)。
当初始化包装器的实例时,它会检查[UIApplication sharedApplication].applicationState != UIApplicationStateBackground
以确定GCD计时器源是否应该最初作为初始化序列的一部分恢复。它还注册UIApplicationDidEnterBackgroundNotification
和UIApplicationWillEnterForegroundNotification
,用于暂停和恢复定时器源(分别)。
我观察到的问题是,在初始化过程中检查[UIApplication sharedApplication].applicationState != UIApplicationStateBackground
似乎已经恢复计时器源, 和 收到的下一个通知是UIApplicationWillEnterForegroundNotification
,这会导致计时器源第二次恢复。这会导致崩溃,因为计时器在第二次恢复时没有暂停。
我可以通过在本地跟踪应用程序状态并确认可能重复的转换来解决这个问题,但我担心我可能会做错误的操作或者可能存在错误(无论是在实现中还是在文档中)。
答案 0 :(得分:2)
这是应用程序状态的工作原理:
首次启动时,
当您点击主页按钮时,
当您打开背景应用时,
打开 - (初始启动和打开后台应用程序) - applicationDidBecomeActive被调用 - 在这里初始化计时器。
隐藏或接听电话等 - 在此处调用applicationWillResignActive - 停止计时器。
希望这有帮助。
答案 1 :(得分:0)
来自UIApplication docs:
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.
因此,你的应用程序可能在后台,很快就会在前台,但目前正在转换。
答案 2 :(得分: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