An often overlooked best practice when implementing Apple Push Notifications (APN) in your iOS applications is verifying that the registration token has not become invalid with each cold start of the app. A cold start happens when application didFinishLaunching
is called (the actual method name is longer and spelled out in the docs linked below).
Here's the outline of what we need to do:
- Call
registerForRemoteNotification
indidFinishLaunching
. This will ask APNS for the registration token. The response is handled in `application didRegisterForRemoteNotificationsWithDeviceToken'. - In
didRegisterForRemoteNotifications
, you will receive the registration token. - Check for the current registration token in
NSUserDefault
. - If the registration token from
NSUserDefault
isnil
or not equal to the registration token that was just passed intodidRegisterForRemoteNotifications
, then...- register for push notifications with PubNub using the new registration token
- save the new registration token in
NSUserDefault
- Otherwise, the registration token has not changed (is still valid), and you do not need to do anything further (you are already registered for push notifications on PubNub channels from the last cold start of the app).
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
PubNub *pubNub = [PubNub clientWithConfiguration:[
PNConfiguration configurationWithPublishKey:@"pub-c-..."
subscribeKey:@"sub-c-..."]
];
self.client = pubNub;
UIUserNotificationType types = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *mySettings =
[UIUserNotificationSettings settingsForTypes:types categories:nil];
// In iOS 8, this is when the user receives a system prompt for notifications in your app
[[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
[[UIApplication sharedApplication] registerForRemoteNotifications];
return YES;
}
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(@"deviceToken: %@", deviceToken);
NSData *oldToken = [[NSUserDefaults standardUserDefaults] dataForKey:@"DeviceToken"];
if (oldToken && [oldToken isEqualToData:deviceToken]) {
// registration token hasn't changed - carry on
return;
}
// remove old token from all PubNub channels for push notifications
[self.client removeAllPushNotificationsFromDeviceWithPushToken:self.devicePushToken
andCompletion:^(PNAcknowledgmentStatus *status) {
NSLog(@"status: %@", status);
// Check whether request successfully completed or not.
// if (status.isError) // Handle modification error.
// Check 'category' property to find out possible issue because
// of which request did fail. Request can be resent using: [status retry];
}
];
[self.client addPushNotificationsOnChannels:@[<array of channels here>]
withDevicePushToken:deviceToken andCompletion:^(PNAcknowledgmentStatus *status) {
NSLog(@"status: %@", status);
[[NSUserDefaults standardUserDefaults] setObject:deviceToken forKey:@"DeviceToken"];
// Check whether request successfully completed or not.
// if (status.isError) // Handle modification error.
// Check 'category' property to find out possible issue because
// of which request did fail. Request can be resent using: [status retry];
}
}
];
}
For more details (but less precise code example), please review the the PubNub iOS SDK Mobile Push Gateway documentation.
Summary
The idea is to always check the validity of the APNS registration token with every cold start of the app, but only update PubNub's mobile push registration when the registration token actually changes for that device.