4

I'm experiencing a weird bug with iOS 10.2 with UNTimeIntervalNotificationTrigger and UNUserNotificationCenterDelegate. Basically the notification I create is getting picked up by the delegate instantly and then again at the correct internal. This only happens when the repeats property is set to true on the trigger.

Has anyone else seen this issue? Right now I'm thinking I need to check the trigger date in the delegate and compare to a stored registered date — but I want to avoid that if possible.

Sample code to create notification

let content = UNMutableNotificationContent()
content.body = "My notification message"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 60, repeats: true)
let request = UNNotificationRequest(identifier: "MY_IDENTIFIER", content: content, trigger: trigger)

UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)

UNUserNotificationCenterDelegate is fired directly after .add

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
      // Code called here instantly when trigger repeats = true
      // Code called again at proper interval as well (60 seconds)
}

If I change the trigger to repeats false, this doesn't happen

  let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 60, repeats: false)
rosem
  • 1,311
  • 14
  • 19
  • Docs say: "If repeats is true, the value in the timeInterval parameter must be 60 seconds or greater." Makes me wonder whether it wouldn't be better to pick a bigger interval and see what happens then, since you are right on the line, as it were. – matt Jan 04 '17 at 18:13
  • It's actually set for multiple days, I just changed it to 60 for the sample code here. – rosem Jan 04 '17 at 19:15

1 Answers1

0

I still haven't found the root problem or have seen/heard anyone else with the issue. In the mean time this was my fix (although I wish it just worked correctly).

I created a dictionary to store the time the notification was fired. I use the notification identifier as the key:

scheduledTimes[identifier] = CACurrentMediaTime()
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)

Then in the delegate, I can compare it to the current time to see if I should ignore it or not:

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    let identifier = notification.request.identifier

    // Required for 10.2?
    // Adding a notification request to the notification center immediately fires this delegate when the trigger is set to repeat
    if let scheduledTime = scheduledTimes[identifier] {
        if CACurrentMediaTime() - scheduledTime < 1.0 {
            completionHandler([])
            return
        }
    }

    // Parse the notification into an internal notification and show it

    completionHandler([])
}

The time between adding and the delegate call is very short, something like 0.04 on average.

rosem
  • 1,311
  • 14
  • 19