LocalNotifications not working properly

Hello,

I have an issue with LocalNotifications on my App.

On my App the user can schedule a Notification to get a reminder when a contract expires. He can choose the date and time himself.
However I have repeatedly been getting E-Mails from users, saying that their Notifications do not work.
When testing on my own personal device however, I have no issue and they work fine.

I was wondering if I was missing some comprehension about LocalNotifications. Do they expire at some point? Does the UNUserNotificationCenter delete queued notifications when a device is turned off? Are there any possible reasons for this behaviour?

Any help would be greatly appreciated as I couldn't find any info online.

I included my code for creating a LocalNotification below:

Code Block
/**
     Schedules a local notification.
     - parameter company: String! of the contracts company name.
     - parameter name: String! of the contracts name.
     - parameter datum: Date! of the reminder.
     - returns: String of NotificationID.
     */
    static func scheduleNotification(company: String!, name: String!, datum: Date!) -> String! {
        let notificationID = arc4random()
        let content = UNMutableNotificationContent()
        content.title = NSLocalizedString("Kündigungserinnerung ", comment: "") + company
        content.body = NSLocalizedString("Falls Sie Ihren ", comment: "") + name + NSLocalizedString(" Vertrag kündigen möchten, wäre jetzt der richtige Zeitpunkt dafür! 📄", comment: "")
        content.categoryIdentifier = Notification.Category.Local.identifier
        content.userInfo = ["NotificationID": notificationID]
        content.sound = UNNotificationSound.default()
        let calendar = Calendar.current
        let components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: datum)
        let finalComponents = NSDateComponents()
        finalComponents.year = components.year!
        finalComponents.month = components.month!
        finalComponents.day = components.day!
        finalComponents.hour = components.hour!
        finalComponents.minute = components.minute!
        let trigger = UNCalendarNotificationTrigger(dateMatching: finalComponents as DateComponents, repeats: false)
        let requestIdentifier = "request"
        let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request, withCompletionHandler: { error in
            if error != nil {
                log.error(error!)
            }
        })
        return String(notificationID)
    }

Accepted Reply

I think what’s happening here is that you are using the same requestIdentifier for each UNNotificationRequest created in your function. Regardless of what date you pass in, you will be replacing any previously scheduled notification on that device with a new notification each time.

See Apple’s documentation: 

“If you use the same identifier when scheduling a new notification, the system removes the previously scheduled notification with that identifier and replaces it with the new one.”
https://developer.apple.com/documentation/usernotifications/unnotificationrequest/1649634-identifier

You could use the notificationID value you generated earlier in the function like this:

let request = UNNotificationRequest(identifier: notificationID, content: content, trigger: trigger)


However,  if you want to give users the functionality to update/replace or cancel a previously scheduled notification, you should generate this notificationID outside your function and store it somewhere. To cancel a notification,  use the removePendingNotificationRequestsWithIdentifiers function call. 

Hope this helps,
  • bvsdev

Replies

I think what’s happening here is that you are using the same requestIdentifier for each UNNotificationRequest created in your function. Regardless of what date you pass in, you will be replacing any previously scheduled notification on that device with a new notification each time.

See Apple’s documentation: 

“If you use the same identifier when scheduling a new notification, the system removes the previously scheduled notification with that identifier and replaces it with the new one.”
https://developer.apple.com/documentation/usernotifications/unnotificationrequest/1649634-identifier

You could use the notificationID value you generated earlier in the function like this:

let request = UNNotificationRequest(identifier: notificationID, content: content, trigger: trigger)


However,  if you want to give users the functionality to update/replace or cancel a previously scheduled notification, you should generate this notificationID outside your function and store it somewhere. To cancel a notification,  use the removePendingNotificationRequestsWithIdentifiers function call. 

Hope this helps,
  • bvsdev