Objective C: Push Notifications in iOS 10

Apple introduced a new framework UserNotifications for delivering and handling of local and remote notifications. Let’s have a look at how to support PUSH notifications in an iOS app.

1. Import UserNotifications.framework in your AppDelegate file

#import <UserNotifications/UserNotifications.h>

Add UNUserNotificationCenterDelegate to the declaration:

#import <UserNotifications/UserNotifications.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate,UNUserNotificationCenterDelegate>
 
@end

2. Register for PUSH notifications

The best place to register for PUSH notifications is the method application:didFinishLaunchingWithOptions:. According Apple’s docs deviceToken can change from time to time. That is why it is important not to cache the device token, but to request it every time on the app start.

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
    [self registerForRemoteNotifications];
    return YES;
}

- (void)registerForRemoteNotifications
{
        // iOS 10 and greater
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        center.delegate = self;
        [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error){
            if(!error){
                dispatch_async(dispatch_get_main_queue(), ^{
                    [[UIApplication sharedApplication] registerForRemoteNotifications];
                });
            }
        }];
}

In the code above you can see the call of requestAuthorizationWithOptions:completionHandler: method. It is important, otherwise no notifications will be displayed to the user. Quote from the Apple’s doc:

If you want your app’s remote notifications to display alerts, play sounds, or perform other user-facing actions, you must request authorization to do so using the requestAuthorizationWithOptions:completionHandler: method of UNUserNotificationCenter. If you do not request and receive authorization for your app’s interactions, the system delivers all remote notifications to your app silently.

It is also important to call registerForRemoteNotifications method on the main thread!

3. Handling of registration for remote notifications

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    // getting device token
    self.devToken = [self stringWithDeviceToken:deviceToken];
}


- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
   // TODO: handle errors here
    
}

// converts deviceToke to String
- (NSString *)stringWithDeviceToken:(NSData *)deviceToken {
    const char *data = [deviceToken bytes];
    NSMutableString *token = [NSMutableString string];
    
    for (NSUInteger i = 0; i < [deviceToken length]; i++) {
        [token appendFormat:@"%02.2hhX", data[i]];
    }
    
    return [token copy];
}

4. Handling delegate methods for UserNotifications

There are two more delegate methods to be implemented:

//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
    NSLog(@"User Info : %@",notification.request.content.userInfo);
    completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
}
 
//Called to let your app know which action was selected by the user for a given notification.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler{
    NSLog(@"User Info : %@",response.notification.request.content.userInfo);
    completionHandler();
}

In iOS 10 it is different with remote notifications during the app is in the foreground. In former iOS versions we had to handle notifications ourselves and display notification to the user, e.g. as Alert message. Now notifications are always shown.

5. Add Push Notifications Entitlements if not done yet

That’s all.
Now your app can receive remote PUSH notifications. Happy Coding!