Reputation: 395
I'm using Objective-c to create a UILocalNotification
in my iPhone app. I'm targeting iOS 8 and using XCode 6.
My problem relates to handling UILocalNotification
when app is not running and it's opened by tapping on a notification. When the user taps the notification and opens the app I use didReceiveLocalNotification
in AppDelegate.m
to show a particular View Controller and send the VC some data (a date).
This works fine when tapping the notification from the lockscreen. When tapping the notification in the Notification Center didReceiveLocalNotification
is never called. I used a UIAlertView
to test this on my device. didFinishLaunchingWithOptions
is called, but when I include the code to show the particular View Controller in that method it never works (though another UIAlertView
showed me it was running that part of the code, just never completing the showViewController
method).
Here's my didFinishLaunchingWithOptions
code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([UIApplication sharedApplication].scheduledLocalNotifications.count >= 1) {
// Handle local notification received if app wasn't running in background
UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if ([[notification.userInfo objectForKey:@"notification"] isEqual:@"mood rating"]) {
// Create reportVC
NSLog(@"launched app and about to show reportvc");
ReportViewController *reportVC = (ReportViewController *)[self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:@"reportVC"];
// Date stuff goes here - code removed
// show the reportVC
[self.window.rootViewController showViewController:reportVC sender:self];
}
} else {
[self createLocalNotification];
}
return YES;
}
And here is my didReceiveLocalNotification
code:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
// Create report view
ReportViewController *reportVC = (ReportViewController *)[self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:@"reportVC"];
// Same date stuff goes here as in didFinishLaunchingWithOptions
// Show report vc
[self.window.rootViewController showViewController:reportVC sender:self];
}
The date stuff that I've take out is just checking if it's after 9pm or not, and either creating today's date or yesterday's, and then setting the result as a property of the reportVC. Let me know if that's relevant and I'll add it back in.
So here's some stuff I've tried to fix this:
I've tried using presentViewController:animated:completion:
instead of showViewController:sender:
but I want to use showViewController
so I can have the navbar show up, and that didn't fix the problem anyway.
I've tried adding this line to my didFinishLaunchingWithOptions
method:
[self application:application didReceiveLocalNotification:notification];
which did kind of fix the problem—when tapping from Notification Center it opened the right view, but it ruined lockscreen notifications. With this line added, when tapping a notification from the lockscreen I got the reportVC presented twice: the first one was a black screen apart from the navbar, and the one on top of that was correct.
I tried replacing my current showViewController
line of code with this instead:
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
[topController showViewController:reportVC sender:self];
but that didn't fix the problem either.
I tried taking the code I've doubled up on out of my didFinishLaunchingWithOptions
method, because I realised didReceiveLocalNotification
seems to be run anyway once didFinishLaunchingWithOptions
is done. That does seem to be the case, but it doesn't fix my problem with Notification Center notifications.
And in case this is screwing it up, here's how I'm testing this at the moment:
I add these two lines to the didFinishLaunchingWithOptions
method:
[[UIApplication sharedApplication] cancelAllLocalNotifications];
[self createLocalNotification];
I change the scheduled time for the notification to be about 3 minutes into the future. It's normally set to go off at 9pm every night using date components like this:
dateComponents.hour = 21;
dateComponents.minute = 0;
And I change the notification's repeatInterval
to be NSCalendarUnitMinute
instead of NSCalendarUnitDay
which is what it's set to for release builds.
Then I run the app on my device using XCode, and stop it once it's run and scheduled the notification. I run it again without these two lines:
[[UIApplication sharedApplication] cancelAllLocalNotifications];
[self createLocalNotification];
And then stop the app from XCode, open multitasking on my device, swipe the app up to close it, and wait for a notification to arrive. After tapping each test notification I multitask and close the app again so I can test from a totally closed app each time.
Upvotes: 4
Views: 987
Reputation: 1474
You may want to try this (present your view controller asynchronously with the dispatch_async()
):
if ([[notification.userInfo objectForKey:@"notification"] isEqual:@"mood rating"]) {
dispatch_async(dispatch_get_main_queue(), ^{
// Create reportVC
NSLog(@"launched app and about to show reportvc");
ReportViewController *reportVC = (ReportViewController *)[self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:@"reportVC"];
// Date stuff goes here - code removed
// show the reportVC
[self.window.rootViewController showViewController:reportVC sender:self];
});
}
or this (call [self.window makeKeyAndVisible]
before presenting your view controller):
if ([[notification.userInfo objectForKey:@"notification"] isEqual:@"mood rating"]) {
// Create reportVC
NSLog(@"launched app and about to show reportvc");
ReportViewController *reportVC = (ReportViewController *)[self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:@"reportVC"];
// Date stuff goes here - code removed
// show the reportVC
[self.window makeKeyAndVisible];
[self.window.rootViewController showViewController:reportVC sender:self];
}
Upvotes: 1