Execute a function when receiving a local notification

I’m trying to execute a function when a local notification is triggered. I have an app that uses local notifications to run a timer, and when the timer finishes I want to save some data to record that the timer has indeed finished. Searching on the internet I was able to write this code:

import SwiftUI
import SwiftData

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
    
    let notificationCenter = UNUserNotificationCenter.current()
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // ... other setup code ...

        notificationCenter.delegate = self

        return true
    }
    
    // Handle notification when the app is in the background or terminated
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let identifier = response.notification.request.identifier
        if let userInfo = response.notification.request.content.userInfo as? [String: Any] {
            if let isTimer = userInfo["isTimer"] as? Bool , isTimer {
                let context = Environment(\.modelContext)
                let fetchDescriptor = FetchDescriptor<Session>()
                do {
                    let sessions = try context.wrappedValue.fetch(fetchDescriptor)
                    if let session = sessions.first(where: { $0.id == identifier }) {
                        session.stopDate = session.startDate.addingTimeInterval(session.timeGoal)
                        do {
                            try context.wrappedValue.save()
                        } catch {
                            print("Error saving context: \(error)")
                        }
                    } else {
                        print("errore nell'aggiornare la sessione")
                    }
                } catch {
                    print("Error accessing context: \(error)")
                    return
                }
            }
        }
        completionHandler()
    }
}

but it seems that the function isn’t called.

Searching some more I found that some people say that this function is called only when the user interacts with the notification, while other people say it’s called every time a notification is received.

My question is: if indeed it’s called every time a notification is received, why my code doesn’t work?
And if it’s called only when a notification is interacted with, is there a way to do what I need?

  • It won’t be called if your app isn’t active. Also Timers don’t work if the app isn’t active. You also can’t do anything if the app is terminated.

    – 




  • The code is only executed if the user taps the notification. There is no way to do what you want, but you don’t need update the data exactly when the timer ends. When your app is next returned to the active state you can check if the timer end date has passed and update your data then.

    – 




  • @loremipsum yeah i know timers don’t work if the app isn’t active, that’s the reason why i’m using local notification to keep track of the timer end date, in the app i have an observable object that every second updates the remaining time. Thanks for confirming it isn’t possible, at least i won’t keep searching for a way.

    – 

  • @Paulw11 oh great, it’s stupid that there’s not a way to do that. I’ll follow your advice thank you

    – 

Leave a Comment