Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

application didReceiveLocalNotification not fired iOS7

The problem:

- (void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification

is not called sometimes with iOS7. It doesn't mater how we schedule the notification:

alarm.fireDate = [[NSDate date] dateByAddingTimeInterval:0.1];
[app scheduleLocalNotification:alarm];

or:

[app presentLocalNotificationNow:alarm];

My thoughts: This happens in the case when the user slides before the notification alert animation is finished. And if he waits just a half second before he slides - the notification is fired and the App proceeds as expected. The problem probably is that application enters foreground before the notification is received.

Did anyone meet this? Is it a bug? Any solution? Thank you!

like image 491
Ahmed Ahmedov Avatar asked Oct 08 '13 09:10

Ahmed Ahmedov


2 Answers

Is your application in the background or foreground? If it's in the foreground, I'm pretty sure that method is called. If it isn't, maybe you aren't putting that method in your application delegate.

If it's on the background, here's a few possible scenarios:

  1. Your app has been killed by the user or the OS. In this case when the user wake up your app by tapping on the notification on the notification centre (or swiping in lock screen), your application delegate will have the application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method called. You can get the notification from this method by:

    [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];

  2. Your app is in background, and the user tap on the notification in notification centre or lock screen. In this case, no delegate methods will be called. The documentation specifically said that didReceiveLocalNotification: is for when the app is in the foreground:

If the app is running in the foreground, there is no alert, badging, or sound; instead, the application:didReceiveLocalNotification: method is called if the delegate implements it.

So hopefully you can make an informed decision about what to do when you receive the notification. I personally find it a little bit weird that we don't get the notification object when the user launches the app by tapping the icon (not the notification). But I currently just write my logic around it.

like image 110
Enrico Susatyo Avatar answered Nov 18 '22 07:11

Enrico Susatyo


Apple explicitly mentions in their documentation (Local and Remote Notification Programming Guide) that different methods get called depending on what state the app is in and what action the user takes (as Enrico mentioned).

Summary:

  • The user taps a custom action button in an iOS 8 notification. In this case, iOS calls either application:handleActionWithIdentifier:forRemoteNotification:completionHandler: or application:handleActionWithIdentifier:forLocalNotification:completionHandler:. In both methods, you get the identifier of the action so that you can determine which button the user tapped. You also get either the remote or local notification object, so that you can retrieve any information you need to handle the action.
  • The user taps the default button in the alert or taps (or clicks) the app icon. ... the system launches the app and the app calls its delegate’s application:didFinishLaunchingWithOptions: method, passing in the notification payload (for remote notifications) or the local-notification object (for local notifications). ...
  • The notification is delivered when the app is running in the foreground. The app calls the UIApplicationDelegate method application:didReceiveLocalNotification: or application:didReceiveRemoteNotification:fetchCompletionHandler:.

So didReceiveLocalNotification is only fired when the app is already running and is in the foreground. You should also handle the second scenario where the isn't running, for which apple has the following code example:

Objective-C:

- (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
    if (localNotif) {
        NSString *itemName = [localNotif.userInfo objectForKey:ToDoItemKey];
        [viewController displayItem:itemName];  // custom method
        app.applicationIconBadgeNumber = localNotif.applicationIconBadgeNumber-1;
    }
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
    return YES;
}

Swift (approximation provided by myself):

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    if let localNotification = launchOptions?[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification {
            if let itemName = localNotification.userInfo?[ToDoItemKey] as? String {
                handleNotification(localNotification)
                application.applicationIconBadgeNumber = localNotification.applicationIconBadgeNumber - 1
            }
    }
    .
    .
    .
}
like image 25
ali-hk Avatar answered Nov 18 '22 09:11

ali-hk