As you know it is not possible to delete a push notification on iOS after it has been received on the device. However, you might have noticed that Facebook app can do that – you receive a push notification about a new message from a friend on your device, but it’s cleared automatically if you read it on your desktop without any interaction with an iOS app. How is this possible?

In this article we’d like to shed some light on how you can achieve the same and explain the method to make push notifications deletable.

The problem here is that iOS does not have an API method to delete push notification from the notification center. On the other hand it does provide a method to delete local notifications!

How push notification could be converted to local notification so it could be deleted later?

The key to this technique is to use a silent push notification that does not display any alert, and then to create a local notification based on the push notification payload.

The very first step is to add “Required background modes” into Info.plist file with the value “App downloads content in response to push notifications”.

PushNotificationsApp-Info_plist

This allows iOS to launch your app in background when a silent push notification is received.

As we want push notification to be silent we cannot put any text in the notification’s title otherwise it would be presented by iOS itself. Therefore, we need to pass title as custom data.

Let’s assume the following push notifications payload:

  • To create a notification we send: {"crt”:NOTIFICATION_ID, "title”:TITLE_TEXT}
    Example: {"crt”:1, "title":"hello there”}
  • To delete a notification: {"dlt”:NOTIFICATION_ID}
    Example: {"dlt":1}

The code below handles these two payloads. Add this in your AppDelegate.m file:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler { //get custom data from push notification NSDictionary *userdata = [[PushNotificationManager pushManager] getCustomPushDataAsNSDict:userInfo]; //check if this is deletable push (check user info for key "dlt":dict) //if this is not null - the dict is the deletable push NSString * dltPushId = [userdata objectForKey:@"dlt"]; if(dltPushId) { //if push is to delete notification "dlt":string" //load notif and delete NSString * pushNotificationId = [NSString stringWithFormat:@"com.pushwoosh.notification.%@", dltPushId]; NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:pushNotificationId]; if(data) { UILocalNotification *notification = [NSKeyedUnarchiver unarchiveObjectWithData:data]; NSLog(@"Remove localnotification %@", notification); //delete it [[UIApplication sharedApplication] cancelLocalNotification:notification]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:pushNotificationId]; return; } } //should we create new push notification NSString * createPushId = [userdata objectForKey:@"crt"]; if(createPushId) { //create local notification of the push //save it UILocalNotification *note = [[UILocalNotification alloc] init]; //we don't need to care about sound or badge as this would be handled already by iOS itself NSString *title = [userdata objectForKey:@"title"]; note.alertBody = title; note.userInfo = userInfo; //present notification now [[UIApplication sharedApplication] presentLocalNotificationNow:note]; //serialize it and store so we can delete it later NSData *data = [NSKeyedArchiver archivedDataWithRootObject:note]; NSString * pushNotificationId = [NSString stringWithFormat:@"com.pushwoosh.notification.%@", createPushId]; [[NSUserDefaults standardUserDefaults] setObject:data forKey:pushNotificationId]; } NSLog(@"Push notification fetch :%@", userInfo); completionHandler(UIBackgroundFetchResultNewData); }
As we have converted push notification to local notification we also need to add extra handlers to our AppDelegate:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { NSLog(@"Local notification :%@", notification); }
And another one to handle local notification on start:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSDictionary * localNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey]; if(localNotification) { NSLog(@"Started with local notification %@", localNotification); }
Now it’s time to test the code! [![1Pushwoosh___Applica1tions___New_Test_App___Send_Push](https://www.pushwoosh.com/wp-content/uploads/2015/02/1Pushwoosh___Applica1tions___New_Test_App___Send_Push-1024x754.png)](https://www.pushwoosh.com/wp-content/uploads/2015/02/1Pushwoosh___Applica1tions___New_Test_App___Send_Push.png)

Make sure you select Silent Push!

2Pushwoosh___Applications___New_Test_App___Send_Push

In the Custom Data field add extra payload:

3Pushwoosh___Applications___New_Test_App___Send_Push

Woosh!

For this example we’ve sent another notification with the following custom data: {"crt":2, "title":"hello there again”}

4IMG_6585

Now let’s delete the first notification – we’ll have to send another push with Custom Data set to: {"dlt":1}

5Pushwoosh___Applications___New_Test_App___Send_Push

Woosh!

6IMG_6586

The drawback is that your application drains a little bit more battery as iOS needs to launch the app every time a notification is received and/or it may delay push notification delivery to your app if your device is low on battery.