apple-push-notificationsios12richpush

Open App from Context of Rich Notification iOS12


I have user interaction enabled on an implementation of UNNotificationContentExtension. How do I open the application once the user is done interacting with UNNotificationContentExtension / ondemand?

Note, that UNNotificationAction is specifically for the pre-programmed action, such as these. I cannot use this, if for example, I wanted the result of a .touchUpInside action on a UIButton to open the application.


Solution

  • To dismiss: self.extensionContext?.dismissNotificationContentExtension()

    To open the application: self.extensionContext?.performNotificationDefaultAction()

    (I tested this, and this worked for me. The dismiss action did not dismiss the notification entirely, just dismissed the context. The performNotificationDefaultAction dismissed the notification and opened the application. At least for me, this was not obvious from the docs and took me a bit to find.)

    In your content extension, implement the optional function for UNNotificationContentExtension below in order to send a response to your application.

    func didReceive(_ response: UNNotificationResponse, completionHandler completion: @escaping (UNNotificationContentExtensionResponseOption) -> Void) {
    
        switch response.actionIdentifier {
        case UNNotificationDismissActionIdentifier:
            // Clearest explanation from Microsoft: https://learn.microsoft.com/en-us/dotnet/api/UserNotificationsUI.UNNotificationContentExtensionResponseOption?view=xamarin-ios-sdk-12
            // Indicates that the notification interface will be dismissed, and that the content extension will handle the action.
            completion(.dismiss)
            // completion(.doNotDismiss)
        case UNNotificationDefaultActionIdentifier:
            // Default action stuff.
            // Let's say the user executed default action, we want to dismiss and forward the action to the app delegate.
            completion(.dismissAndForwardAction)
            break
        default:
            break
        }
    

    To receive the response, in your app delegate, implement the function below of the UNUserNotificationCenterDelegate protocol. You can use the same switch statement as above.

    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        // Received user info is given by response.notification.request.content.userInfo.
    }
    

    We can read the userInfo and take an action based on that in the delegate. But what if that action changes based on the user's interactions in the notification interface? For example, the content of the notification is the same, but the user pressed a button in your interface that says "Open URL" and not the other button that says "Take Action." We cannot open a URL from the interface, so we have to somehow forward this action (and not the other, standard action) to the application.

    I am unsure how to do this best [1]. Please comment below if you have a solution! I am currently using UIPasteboard, which allows sharing between different applications on the Apple device. This might be one of the few solutions because your main application and the notification content extension are entirely different targets. Here are the simple CRUD actions for Pasteboard.

    let pasteboard = UIPasteboard.init(name: "myApp", create: true)
    

    Set in the context interface; read in the AppDelegate.

    [1] Could do a Cloud solution, but not ideal. Also, UserDefaults does not work (hence, Pasteboard; tried UserDefaults).