iosswiftswiftuiapple-push-notifications

Remote notification tap not handled when app is killed


I’m running into an issue with remote push notifications on iOS.

When the app is in background or inactive, tapping a notification correctly triggers:

userNotificationCenter(_:didReceive:withCompletionHandler:)

…but when the app is terminated (killed), tapping the notification launches the app, yet no delegate method is called, and my tracking event never gets sent.

I’m using:

I’ve tried:

Foreground + background tap handling works perfectly — only killed → tap → launch fails to deliver the payload. hell i can't even see logging for that flow.

Some code i have:

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions:[UIApplication.LaunchOptionsKey : Any]?
    ) -> Bool {
        
        UNUserNotificationCenter.current().delegate = self
        return true
    }

func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        didReceive response: UNNotificationResponse,
        withCompletionHandler completionHandler: @escaping () -> Void
    ) {
        handleNotificationTap(response.notification.request.content.userInfo)
        completionHandler()
    }

    public func handleNotificationTap(_ userInfo: [AnyHashable : Any]) {   
        let id = userInfo["notification_id"]
        let notificationId = (id as? Int).map(String.init) ?? (id as? String)

        if let finalId = notificationId {
            Analytics.track("notification_opened", parameters: ["notification_id": finalId])
        } else {
            Analytics.track(
                "notificationTappedWithoutID",
                parameters: ["payload": userInfo]
            )
        }
    }

As you can see there should always be some event send, but currently i receive none. i also tried didReceiveRemoteNotification but that didn't work either.

Any help would be appreciated. been looking in to this for a few nights now.


Solution

  • You can also try adding these two AppDelegate methods.

    First one:

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        if let userInfo = launchOptions?[.remoteNotification] as? [AnyHashable: Any] {
            NotificationCenter.default.post(
                name: Notification.Name("didTapRemoteNotification"),
                object: nil,
                userInfo: userInfo
            )
        }
        return true
    }
    

    This runs when the app launches. If iOS actually includes the push payload in launchOptions, you just forward it to the app.

    Second one:

    func application(_ application: UIApplication,
                     didReceiveRemoteNotification userInfo: [AnyHashable : Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        NotificationCenter.default.post(
            name: Notification.Name("didTapRemoteNotification"),
            object: nil,
            userInfo: userInfo
        )
        completionHandler(.noData)
    }
    

    This one handles incoming remote notifications, including silent ones.

    Both methods basically try to catch the notification payload as early as possible and pass it into the app. They can help when UNUserNotificationCenterDelegate doesn’t fire after a cold start.