问题
The app that I have made keeps track of Goals and Milestones(which belong to a goal) and reminds the user when they are about to reach the due date of a goal or a milestone through a UILocalNotification
my app has been successful in handling local notifications when the app is in a background state and when the app is in the foreground.
I am aware that if you want to handle local notifications when they are received when the app is terminated you are required to access the local notification through the launch options of the application:didFinishLaunchingWithOptions: method in your appDelegate.
However whenever I test the app and activate the local notification after the app has terminated, I am unable to handle the local notification in application:didFinishLaunchingWithOptions:
I suspect it has something to do with either launch options being nil or launch options not having the local notification payload.
The way I test this scenario is as such:
- I build and run the app (command + R)
- I schedule the notification
- I stop running the simulator and then change my mac's time to just before the fire date
- I build and run the app again and then proceed to terminate the app from the simulator (by shift + command + h twice and then swiping up)
- I lock the screen and wait for the notification
- After it fires I swipe the notification on the lock screen
After the notification fires and i swipe the notification, the app is launched but the method that i used in handling the local notification payload in application:didFinishLaunchingWithOptions: is not called whatsoever.
My Code in my application:didFinishLaunchingWithOptions: to handle the local notification payload is as follows:
if let options = launchOptions {
let value = options[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification
if let notification = value {
self.application(application, didReceiveLocalNotification: notification)
}
}
My Code in my application:didReceiveLocalNotification: is as follows:
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
//If the user receives a notification while app is in the foreground
println("")
if application.applicationState == UIApplicationState.Active {
println("did receive notification")
UIApplication.sharedApplication().applicationIconBadgeNumber = 0
let alertController = UIAlertController(title: nil, message: notification.alertBody!, preferredStyle: UIAlertControllerStyle.Alert)
let alertAction = UIAlertAction(title: "View", style: UIAlertActionStyle.Default) { (alertAction) -> Void in
self.performFollowUpActionForNotification(notification)
}
let cancelAction = UIAlertAction(title: "Close", style: UIAlertActionStyle.Cancel, handler: nil)
alertController.addAction(alertAction)
alertController.addAction(cancelAction)
self.window!.rootViewController!.presentViewController(alertController, animated: true, completion: nil)
}
else {
performFollowUpActionForNotification(notification)
application.applicationIconBadgeNumber = 0
}
}
as well as the helper method performFollowUpActionForNotification:
func performFollowUpActionForNotification(notification:UILocalNotification) {
if notification.alertAction! == "View Goal" {
if let tabVC = self.window?.rootViewController? as? UITabBarController {
let navCon = tabVC.viewControllers![0] as UINavigationController
if navCon.topViewController is GoalPageViewController {
}
else {
navCon.pushViewController(navCon.viewControllers![0] as UIViewController, animated: true )
}
}
}
if notification.alertAction! == "View Milestone" {
if let tabVC = self.window?.rootViewController? as? UITabBarController {
let navCon = tabVC.viewControllers![0] as UINavigationController
if let goalPageVC = navCon.viewControllers![0] as? GoalPageViewController {
goalPageVC.findGoalThatContainsMilestoneAndGoToDetailForNotification(notification)
}
else {println("cant down cast view controller to goal page view controller")}
}
}
}
Is the problem with my code or how i test my app for this scenario? I am desperately in need of an answer.
回答1:
Hope this will be helpful for you please have look below.
In iOS 7.1 Apple has introduced a very important update to how the system handles notifications triggered by beacons. Now an app can take action when enter/exit monitoring events occur, even if it has been terminated. It’s an amazing improvement in comparison to iOS 7, but there’s still a lot of confusion regarding how it really works, so we’ve prepared a short tutorial.
Location events (related to the beacons in this case) are handled the same way as any other app launching events. Every single time phone enters or exits beacon’s region while the app is terminated, it will be automatically launched and application:didFinishLaunchingWithOptions: method (of AppDelegate class) is called with UIApplicationLaunchOptionsLocationKey key existing in launchOptions parameter.
When you verify this key exists (so location was the reason that your app was launched) you should create new instance of ESTBeaconManager class, set delegate to AppDelegate object (or any other object that is working as ESTBeaconManagerDelegate and was created before this event occurred) and start monitoring. Region you are passing to the startMonitoringForRegion: method is not important, as ESTBeaconManager delegate will receive most recent region information. You can just pick any of the ones your app registered in iOS. When the monitoring was revoked, app will automatically receive most recent entered/exited region event in beaconManager:didEnterRegion: or beaconManager:didExitRegion: method.
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if([launchOptions objectForKey:@"UIApplicationLaunchOptionsLocationKey"])
{
self.beaconManager = [ESTBeaconManager new];
self.beaconManager.delegate = self;
// don't forget the NSLocationAlwaysUsageDescription in your Info.plist
[self.beaconManager requestAlwaysAuthorization];
[self.beaconManager startMonitoringForRegion:[[ESTBeaconRegion alloc]
initWithProximityUUID:ESTIMOTE_PROXIMITY_UUID
identifier:@"AppRegion"]];
}
return YES;
}
-(void)beaconManager:(ESTBeaconManager *)manager didEnterRegion:(ESTBeaconRegion *)region
{
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = @"Enter region";
notification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}
-(void)beaconManager:(ESTBeaconManager *)manager didExitRegion:(ESTBeaconRegion *)region
{
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = @"Exit region";
notification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}
来源:https://stackoverflow.com/questions/27900876/unable-to-handle-local-notification-when-app-has-been-terminated