Cancel and reschedule UserNotification(old UILocalNotification) starting from custom date in iOS 10

1.4k views Asked by At

I'm scheduling a daily UserNorification to trigger everyday at a specific time, notifying the user to do something. But if the user does that X hours before the notification is fired, I need to cancel today's notification, in my opinion cancel all, and reschedule again but from tomorrow's specific time. For example, if today the notification should fire at 11:00 and the user "do that thing" at 10:00, the 11:00 notification should not be fired, and I need to schedule again at the same time but starting from tomorrow. And the cycle goes on and on, same for tomorrow. My questions are:

  1. Should I unschedule the first daily notifications using the following code: UNUserNotificationCenter.current().removeAllPendingNotificationRequests() ?

  2. How to schedule daily notifications starting from a specific date?

2

There are 2 answers

1
Slavcho On BEST ANSWER

After researching, this is not possible with the new UserNotifications Framework. We must use the old UILocalNotification approach to achieve this. Because that code is deprecated in iOS10, I've changed the supported version to be from 9+, so there will be no warnings. This is a permanent approach, but lets hope that Apple will implement and extend the old feature in the new framework.

11
spassas On

Unfortunately, this kind of scheduling became ridiculously hard with the notifications framework in iOS 10. The only way I could find to do something similar is to use a hybrid of both UNCalendarNotificationTrigger and UNTimeIntervalNotificationTriggerAND implement a UNNotificationContentExtension.

The concept is the following:

Every time your action is being performed you need to reschedule your notifications. If the time is earlier than the desired notification time (e.g 11:00 in your example), instead of using a calendar trigger to reschedule, use a time interval trigger to set one, temporary, non-repeating notification for the next day (let's call it tempNotification)

let nextDayAt11AMDate = /* the timestamp of tomorrow at 11am */
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: nextDayAt11AMDate.timeIntervalSinceDate(NSDate()), repeats: false)
/* schedule tempNotification */

When this notification is received (and provided that a UNNotificationContentExtension has been implemented), in your extension's view controller didReceive: method which is called when the notification arrives, cancel existing notifications and schedule the actual, repeating notification normally using a calendar trigger (let's call it actualNoticfication)

let date = DateComponents()
date.hour = 11
date.minute = 00 
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
/* schedule actualNotification */

It's a long work-around, probably not very efficient and also not 100% reliable (e.g if the device is closed when the tempNotification arrives then the actualNotification will not be scheduled) but it covers the majority of cases. I would be very glad to find a better way than that...