应用程序:didFinishLaunchingWithOptions:在创build目标控制器之前触发通知

您好,我正在编写一个应用程序,当使用本地通知打开它时,应用程序会响应UI更新和内部状态更改。 我正在使用故事板,并设置了我的主视图控制器来观察状态更改:

- (void)viewDidLoad { [super viewDidLoad]; // ... [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resumeByNotification:) name:@"Resume" object:nil]; } 

在我的应用程序代表我有这个:

 - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { if (application.applicationState == UIApplicationStateInactive) { [[NSNotificationCenter defaultCenter] postNotificationName:@"Resume" object:self userInfo:notification.userInfo]; } } 

这工作得很好:如果应用程序在后台运行,视图控制器将拦截通知并作出相应的反应。 (如果应用程序在前台运行,则由于正在直接处理用户界面,所以将忽略它。)

应用程序被杀并收到通知时出现问题。 我已经写在didFinishLaunchingWithOptions方法,使手机震动作为一个快速debugging技术:),我得到的通知:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UILocalNotification *localNotification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]; if (localNotification) { [[NSNotificationCenter defaultCenter] postNotificationName:@"Resume" object:self userInfo:localNotification.userInfo]; AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); } return YES; } 

手机会振动,所以通知在那里,但似乎并没有触发观察者。 我想这是因为视图控制器didViewLoad方法还没有被调用。 我不知道如何解决这个问题。 我想我可以使用UIStoryboard的instantiateViewControllerWithIdentifier:方法来确保视图控制器实际上存在,但除了最终将由故事板的生命周期实例化之外,我不会得到它的“额外”实例? 从class上的参考文献所说的话来看,这并不完全是为了做这种事情。

我在这里错过了非常明显的东西吗? 事实上,对于这种情况,我的方法是否正确呢?

谢谢!

视图控制器不会加载它的视图,直到有东西要求它的视图。 在启动时,这通常发生在application:didFinishLaunchingWithOptions:返回之后。

你可能想知道为什么。 答案是你可能会在启动的时候实例化几个视图控制器,其中一些是隐藏的。 例如,如果你的窗口的根视图控制器是一个UINavigationController ,你可能会用一堆视图控制器(用户上次运行应用程序时推送的栈)加载导航控制器。 只有这个堆栈的顶部视图控制器是可见的,所以不需要加载其他视图控制器的视图。 系统等待直到application:didFinishLaunchingWithOptions:在加载任何视图之前返回,以便只加载必要的视图。

所以解决你的问题的一个办法就是问视图控制器的视图,从而迫使它加载。 如果你的视图控制器是窗口的根视图控制器,你可以这样做:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UILocalNotification *localNotification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]; if (localNotification) { [[self.window rootViewController] view]; [[NSNotificationCenter defaultCenter] postNotificationName:@"Resume" object:self userInfo:localNotification.userInfo]; AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); } return YES; } 

一个不同的解决方法是开始观察你的视图控制器的initWithCoder:方法中的通知:

 - (id)initWithCoder:(NSCoder *)aDecoder { if (self = [super initWithCoder:aDecoder]) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resumeByNotification:) name:@"Resume" object:nil]; } return self; } 

当从MainStoryboard实例化视图控制器时,这会在application:didFinishLaunchingWithOptions: message之前发生。