Schedule start of notification requests

Hello all,

I have an app that allows users to create a repeating event. Based on user-provided start date and repeat pattern (daily, weekly, monthly, etc.), the app schedules a repeating notification using UNUserNotificationCenter with a UNCalendarNotificationTrigger.

If the repeat pattern is daily, the user receives notifications each day at the specified time. This works perfectly.

But because UNCalendarNotificationTrigger uses a start date and matches components (in the case of daily repetition, it matches the timezone, hour, minute, and second), if the user enters a start date that is in the future, UNCalenderNotificationTrigger fires before the selected start date because all it does is match components.

Does anyone have ideas for a solution to how I could fix this issue? I was thinking maybe scheduling the scheduling of the notification for a day in advance of the event. I don't want to use a for loop to create multiple notifications because that it difficult to manage.
You may register a notification with specifying the start date, no repeating. You can re-register the everyday notification when processing the date specified notification.


Or you can register a next notification at each time you received a date specific notification.
I think your second idea is what I might use, because of this: each event a user creates has a UUID stored in Core Data. The notification identifier is the same as the UUID, so when a user deletes an event, it's really simple to delete the pending notification request. Using your method of creating a new notification when the current one fires, can I recycle the same UUID and keep using that UUID for the future notifications?

Also, I'm not familiar with how to schedule a new notification when the existing one fires. What function is that?

Also, I'm not familiar with how to schedule a new notification when the existing one fires. What function is that?

Please show your code currently registering notification and handling notification. You once wrote This works perfectly.
Code Block
    func sendNotification(title: String, subtitle: String?, body: String, time: Date, id: UUID, repeatPattern: String) {
        let content = UNMutableNotificationContent()
        content.title = title
        if let subtitle = subtitle {
            content.subtitle = subtitle
        }
        content.body = body
        content.sound = UNNotificationSound.default
        
        let triggerDate = time - 5 * 60
        if repeatPattern == "Daily" {
            let trigger = UNCalendarNotificationTrigger(dateMatching: Calendar.current.dateComponents([.second], from: triggerDate), repeats: true)
            let request = UNNotificationRequest(identifier: "\(id)", content: content, trigger: trigger)
            UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
        } else if repeatPattern == "Weekly" {
            let trigger = UNCalendarNotificationTrigger(dateMatching: Calendar.current.dateComponents([.timeZone, .weekday, .hour, .minute, .second], from: triggerDate), repeats: true)
            let request = UNNotificationRequest(identifier: "\(id)", content: content, trigger: trigger)
            UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
        } else if repeatPattern == "Monthly" {
            let trigger = UNCalendarNotificationTrigger(dateMatching: Calendar.current.dateComponents([.timeZone, .weekOfMonth, .weekday, .hour, .minute, .second], from: triggerDate), repeats: true)
            let request = UNNotificationRequest(identifier: "\(id)", content: content, trigger: trigger)
            UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
        } else if repeatPattern == "None" {
            let trigger = UNCalendarNotificationTrigger(
                dateMatching: Calendar.current.dateComponents([.timeZone, .year, .month, .day, .hour, .minute], from: triggerDate), repeats: true)
            let request = UNNotificationRequest(identifier: "\(id)", content: content, trigger: trigger)
                    UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
        }
}



Calling the function in the add meeting modal :

Code Block
self.notificationManager.sendNotification(title: "Upcoming Meeting", subtitle: nil, body: "\(meetingName) will start in 5 minutes. Tap for meeting information.", time: newMeeting.time!, id: newMeeting.id!, repeatPattern: "\(repeats)")
print("Scheduled repeating notification.")

Please show your code currently registering notification and handling notification.

Waiting for the code handling notification.


Code Block
class LocalNotificationManager: ObservableObject {
    
    @Environment(\.managedObjectContext) private var viewContext
    var meetings: Item?
    
    var notifications = [Notification]()
    
    init() {
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
            if granted == true && error == nil {
                print("Notifications permitted")
            } else {
                print("Notifications not permitted")
            }
        }
    }
    
    func sendNotification(title: String, subtitle: String?, body: String, time: Date, id: UUID, repeatPattern: String) {
        let content = UNMutableNotificationContent()
        content.title = title
        if let subtitle = subtitle {
            content.subtitle = subtitle
        }
        content.body = body
        content.sound = UNNotificationSound.default
        
        let triggerDate = time - 5 * 60
        if repeatPattern == "Daily" {
            let trigger = UNCalendarNotificationTrigger(dateMatching: Calendar.current.dateComponents([.second], from: triggerDate), repeats: true)
            let request = UNNotificationRequest(identifier: "\(id)", content: content, trigger: trigger)
            UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
        } else if repeatPattern == "Weekly" {
            let trigger = UNCalendarNotificationTrigger(dateMatching: Calendar.current.dateComponents([.timeZone, .weekday, .hour, .minute, .second], from: triggerDate), repeats: true)
            let request = UNNotificationRequest(identifier: "\(id)", content: content, trigger: trigger)
            UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
        } else if repeatPattern == "Monthly" {
            let trigger = UNCalendarNotificationTrigger(dateMatching: Calendar.current.dateComponents([.timeZone, .weekOfMonth, .weekday, .hour, .minute, .second], from: triggerDate), repeats: true)
            let request = UNNotificationRequest(identifier: "\(id)", content: content, trigger: trigger)
            UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
        } else if repeatPattern == "None" {
            let trigger = UNCalendarNotificationTrigger(
                dateMatching: Calendar.current.dateComponents([.timeZone, .year, .month, .day, .hour, .minute], from: triggerDate), repeats: true)
            let request = UNNotificationRequest(identifier: "\(id)", content: content, trigger: trigger)
                    UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
        }
        let center = UNUserNotificationCenter.current()
        center.getPendingNotificationRequests(completionHandler: { requests in
            for request in requests {
                print(request)
                
            }
        })
    }
}

I guess I have chosen a bad term.
Please show your code responding to notifications.
You could call from
Code Block
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
if notification.request.identifier == requestIdentifier {
completionHandler( [.alert,.sound,.badge])
// schedule next notification here
}
}


I'm a little confused as to what you mean by calling that function. Where would I call that function? And what is the requestItentifier in that function?
This function is called when a notification is presented.

If you want to filter on a specific notification, you set requestIdentifier to the appropriate request identifier that was defined at creation.

I'm a little confused as to what you mean by calling that function. Where would I call that function? And what is the requestItentifier in that function?

Seems you do not know how to respond to user notifications.
Please show your code instantiating your LocalNotificationManager.
Apple's interface here is awful. All that is necessary is to add a start date. Why can't they add it?????? It would make developers' lives so much easier. 😡
Schedule start of notification requests
 
 
Q