lawayben
lawayben

Reputation: 71

How save data in UserDefaults when the user press UNNotificationAction and the app is closed?

If the app is opened or in the background, userNotificationCenter get triggered and the data get saved just fine, but if the app is closed, when the notification comes, and I press one of the action buttons, nothing happens, the data doesn't get saved.

This is the code:

UNUserNotificationCenter.current().delegate = self
        
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound, .criticalAlert]
        UNUserNotificationCenter.current().requestAuthorization(options: authOptions, completionHandler: { (granted, error) in
                if granted {
                    
                }
            })
        
        let PKW = UNNotificationAction(identifier: "PKW", title: "Komme per PKW", options: .foreground)
        let Fuß = UNNotificationAction(identifier: "Fuß", title: "Komme per Fuß", options: .foreground)
        let Rad = UNNotificationAction(identifier: "Rad", title: "Komme per Rad", options: .foreground)
        let nicht = UNNotificationAction(identifier: "Nicht", title: "Komme per Komme nicht", options: .foreground)
        let category = UNNotificationCategory(identifier: "ComeBy", actions: [PKW, Fuß, Rad, nicht], intentIdentifiers: [], options: [])
        UNUserNotificationCenter.current().setNotificationCategories([category])

        application.registerForRemoteNotifications()
func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent: UNNotification,
                                withCompletionHandler: @escaping (UNNotificationPresentationOptions)->()) {
        withCompletionHandler([.alert, .sound, .badge])
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler: @escaping ()->()) {
        let eventData = response.actionIdentifier
        switch eventData {
        case "PKW", "Fuß", "Rad", "Nicht":
            UserDefaults.standard.set(eventData, forKey: prefixedKey(UserDefaultsKeys.comeBy.key))
        default:
            break
        }

        
        withCompletionHandler()
    }

enter image description here

Upvotes: 0

Views: 67

Answers (3)

lawayben
lawayben

Reputation: 71

The issue was related to @capacitor/ios at the end of the day, since I was trying to implement a custom notifications inside AppDelegate, and to make it work, I had to patch the package, and get ride of any use of UNUserNotificationCenterDelegate

Upvotes: 0

Suryakant Sharma
Suryakant Sharma

Reputation: 3960

App Terminated: The app relaunches, and userNotificationCenter(_:didReceive:withCompletionHandler:) is invoked directly.

https://developer.apple.com/documentation/usernotifications/unusernotificationcenterdelegate/usernotificationcenter(_:didreceive:withcompletionhandler:)

Use this method to process the user’s response to a notification. If the user selected one of your app’s custom actions, the response parameter contains the identifier for that action. (The response can also indicate that the user dismissed the notification interface, or launched your app, without selecting a custom action.) At the end of your implementation, call the completionHandler block to let the system know that you are done processing the user’s response. If you do not implement this method, your app never responds to custom actions.

// Handle notification responses when app is running or just launched

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let actionIdentifier = response.actionIdentifier // using actionIdentifier you know which button is pressed.

    switch actionIdentifier {
    case "PKW", "Fuß", "Rad", "Nicht":

        print("Button pressed: \(actionIdentifier)")
        // Save the data
        UserDefaults.standard.set(actionIdentifier, forKey: prefixedKey(UserDefaultsKeys.comeBy.key))
    default:
        print("Default action or no button pressed")
    }

    completionHandler()
}

Upvotes: 0

Ashish Yadav
Ashish Yadav

Reputation: 11

In app's active and running state, press on Notification in handled by willPresent and didReceive function.

But in app's closed state if we press on notification, app will launch and we can identify the same using launchOptions

func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        UNUserNotificationCenter.current().delegate = self
        
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound, .criticalAlert]
        UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { (granted, error) in
            if granted {
                self.setupNotificationCategories()
            }
        }
        
        application.registerForRemoteNotifications()
        
        // Handle notification if app is launched from a closed state
        if let notificationResponse = launchOptions?[.remoteNotification] as? [String: AnyObject] {
            handleNotificationAction(userInfo: notificationResponse)
        }
        return true
    }

Hope this info will work for you. Happy Coding :)

Upvotes: 0

Related Questions