I'm working with UILocalNotification
and I would like to notify one of my controller that the notification has been received even if the app has been terminated.
In my appDelegate I implemented this function:
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
if ([application applicationState] == UIApplicationStateInactive) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"localNotificationReceived" object:notification.userInfo];
}
}
In my UIViewController
I implemented the observer on the viewDidLoad
method
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didlocalNotificationReceived:) name:@"localNotificationReceived" object:nil];
}
It works perfectly when the app run in background. Since the viewDidLoad
method has already been called and the Observer is waiting..
The issue is when I kill the app. Then the observer of my controller is gone and the didlocalNotificationReceived
method is never called.
I think that it's because when I receive the localNotification
and run the app again. The didReceiveLocalNotification:
method is called before the viewDidLoad
of my UIViewController
. Then the observer is created after the PostNotificationName
then the observer receives nothing.
I would like to know if there is some best practices or pattern to handle this kind of issue.
I know that the didFinishLaunchingWithOptions
method is called before didlocalNotificationReceived
so there is probably something to do there.
UPDATE :
I also discovered that when is app is terminated. Once you tap the notification, It opens the app, call the function didFinishLaunchingWithOptions
but never call didReceiveLocalNotification
. So I think that I'm gonna handle both cases differently.
Ok I found the answer.
I actually, initialize manually my storyboard, and be cautious that I initialize my main view before posting the NSNotification
My didFinishLaunchingWithOptions:
method in my appDelegate
looks like that:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
UIViewController *vc =[storyboard instantiateInitialViewController]; //call the initWithCoder: method of my controller
if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) {
UILocalNotification *localNotification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
[[NSNotificationCenter defaultCenter] postNotificationName:@"localNotificationReceived" object:localNotification.userInfo];
}
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
return YES;
}
Then in my UIViewController
I create the NSNotification
observer in the initWithCoder:
method instead of in viewDidLoad:
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didlocalNotificationReceived:) name:@"localNotificationReceived" object:nil];
}
return self;
}
- (void)didlocalNotificationReceived:(NSNotification *)notification
{
//Execute whatever method when received local notification
}
And when the app is not killed I still use the didReceiveLocalNotification:
method:
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
if ([application applicationState] == UIApplicationStateInactive) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"localNotificationReceived" object:notification.userInfo];
}
}
I'm not sure if it's the best practice. But it works well !
Hope it'll help :)