Search code examples
iosobjective-cuilocalnotification

Local notification views to appear in foreground


I need local notifications to display in foreground. I read that this is possible in the introduced in iOS10 UserNotifications framework. I try to implement it and get the notifications only in background. In foreground -(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification gets called but the view of the notification is not shown. I would like it to show on both foreground and background, to be tappable and to trigger a method when tapped. Is this possible and what am I missing in my code if yes. This is the code: In AppDelegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.

UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
UNAuthorizationOptions options = UNAuthorizationOptionAlert + UNAuthorizationOptionSound;
[center requestAuthorizationWithOptions:options
                      completionHandler:^(BOOL granted, NSError * _Nullable error) {
                          if (!granted) {
                              NSLog(@"Something went wrong");
                          }
                      }];

return YES;
}

-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
NSLog(@"Will present notification");
}

-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
NSLog(@"Did Receive Notification Response");
}

In a ViewController:

- (void)locationManagerDidEnterRegionOfCamera:(NSString *)cameraName {
NSDictionary *info = @{ kRegionNotificationDictionaryCameraName : cameraName };

// Check if the switch was previously set to off and not fire notification
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"switch"]) {

    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0.0")) {
        UNMutableNotificationContent *content = [UNMutableNotificationContent new];
        content.title = @"Don't forget";
        content.body = @"Buy some milk";
        content.sound = [UNNotificationSound defaultSound];

        UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1
                                                                                                        repeats:NO];

        NSString *identifier = @"UYLLocalNotification";
        UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier
                                                                              content:content trigger:trigger];

        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
            if (error != nil) {
                NSLog(@"Something went wrong: %@",error);
            } else {

            }
        }];

    } else {
        [NotificationsHelper scheduleRegionNotificationWithInfo:info];
    }
}
}

Solution

  • The important method is this one: userNotificationCenter:willPresentNotification:withCompletionHandler:

    From the documentation:

    completionHandler The block to execute with the presentation option for the notification. Always execute this block at some point during your implementation of this method. Specify an option indicating how you want the system to alert the user, if at all. This block has no return value and takes the following parameter:

    options The option for notifying the user. Specify UNNotificationPresentationOptionNone to silence any alerts. Pass other values to specify which types of alerts you want to allow. For information about the available alert options, see UNNotificationPresentationOptions.

    Additional Infos on Apple Programming Guide

    What's the plan:

    Let's say that you receive 2 types of notifications, by you want to handle them differently, for one you want to show the alert even if the app is in foreground, and the other one just a sound. That's why you use this method.

    Analyse the UNNotification, and according to your choices, at the end, call completionHandler(someValue), where someValue is a UNNotificationPresentationOptions (it's a flag in reality, you should be able to combine them). The one you want at least is UNNotificationPresentationOptionAlert.

    Sample code:

    - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
       UNNotificationPresentationOptions options;
       //Read the notification object, parse some info, decide on what do to by settings options
       if (something)
       {
           //Show badge
           options = UNNotificationPresentationOptionBadge;
       } 
       else if (somethingElse) 
       {
           //Show alert and make sound
           options = UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert;
       } 
       else ...
    
       completionHandler(options);
    }