Raw Bit Rabbit
Raw Bit Rabbit

Reputation: 638

iOS Local Notification based on date time set by user in ToDo DatePicker (Swift & SwiftUI)

I'm learning by applying and have been able to build up a todo app with title, priority and due date and pass that through core data and display it on a list view.

At this point using the following code. I've been able to launch a pop up requesting user consent for notifications.

Function Used

func requestPush() -> Void {
    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
        if success {
            print("All set!")
        } else if let error = error {
            print(error.localizedDescription)
        }
    }
}

Called in Content View using

.onAppear(perform: requestPush)

At this point I've tried several solutions to use the date from the date picker for each todo item and set a reminder. However I am not able to get the schedule Local Notification function to work.

Here is what I've been working with so far.

func scheduleNotification() -> Void{
    let content = UNMutableNotificationContent()
    content.title = "Your title"
    content.body = "Your body"
    
    var setReminder = Date()
    
    if setReminder < Date() {
        if let addedValue = Calendar.current.date(byAdding: .minute, value: 1, to: setReminder) {
            setReminder = addedValue
        }
    }
    
    let comps = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: setReminder)
    
    let trigger = UNCalendarNotificationTrigger(dateMatching: comps, repeats: false)
    
    let request = UNNotificationRequest(identifier: "alertNotificationUnique", content: content, trigger: trigger)
    
    UNUserNotificationCenter.current().add(request) {(error) in
        if let error = error {
            print("Uh oh! We had an error: \(error)")
        }
    }
}

Any suggestions or guidance on how I can set up local notifications based on each todo item due date?

Note: Codes are based on various solutions available on the web. This is the one that worked for me to the point of collecting user approval for notifications.

Upvotes: 0

Views: 2046

Answers (2)

Artem Chernousov
Artem Chernousov

Reputation: 509

It's difficult to say without seeing the whole code and possibility to debug what exactly wrong, so I wrote small example here https://github.com/yellow-cap/swiftui-local-notifications.

The main files to explore: LocalNotificationsApp.swift, NotificationManager.swift, ContentView.swift

If you will have any questions, feel free to ask.

UPDATED AFTER CODE REVIEW:

Schedule notification action

    func scheduleNotification() {
        let timeIntervalMinutes = 1
        let notificationManager = // get NotificationManager
         
        // create notification content
        let content = UNMutableNotificationContent()
        content.title = "Example title"
        content.body = "Example body"

        // create trigger (will show notification 1 min before selected time)
        let triggerDate = self.setReminder.addingTimeInterval(Double(-timeIntervalMinutes * 60))
        let trigger = UNCalendarNotificationTrigger(
            dateMatching: Calendar.current.dateComponents([.timeZone, .year, .month, .day, .hour, .minute], from: triggerDate),
            repeats: false
    )

    notificationManager.scheduleNotification(
            id: "Example id",
            content: content,
            trigger: trigger)
}

Notification manager scheduleNotification function:

    func scheduleNotification(id: String, content: UNNotificationContent, trigger: UNNotificationTrigger) {
        let request = UNNotificationRequest(identifier: id, content: content, trigger: trigger)
        notificationCenter.add(request)
}

Full code of the NotificationManager: https://github.com/yellow-cap/swiftui-local-notifications/blob/main/LocalNotifications/LocalNotifications/NotificationManager.swift

Upvotes: 2

Ernist Isabekov
Ernist Isabekov

Reputation: 1233

i suspect its not work because date comparison statement.

if setReminder < Date() {
        if let addedValue = Calendar.current.date(byAdding: .minute, value: 1, to: setReminder) {
            setReminder = addedValue
        }
    }

should be

var setReminder = Date().addingTimeInterval(10)    
let comps = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: setReminder)

Upvotes: 1

Related Questions