didReceiveRemoteNotification Method in AppDelegate never called

Dear fellow developers, I have an issue where my didReceiveRemoteNotification method in the AppDelegate is never called. Here's what I did:

  • I am developing a SwiftUI application for iOS 15 and 16 and am currently running tests in an iPhone 14 Pro Simulator. My Xcode version is 14.2 and the simulator is running iOS 16.2.

  • I am of course talking about the AppDelegate's application:didReceiveRemoteNotification:fetchCompletionHandler: method, not the deprecated one.

  • I embedded the AppDelegate in the following way:

@main
struct MyApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    ...
}
  • The integration of my AppDelegate does work in general, meaning the didFinishLaunchingWithOptions is called.

  • I added the background modes capability to my app, including both "Remote notifications" and "Background processing".

With this configuration, I would expect the AppDelegate's method to be called. I tried sending different push notifications with different payloads and headers while having the app both in the background and foreground but without success.

Just to rule out mistakes on my side that are obvious to someone else, this is how I embedded the method into my AppDelegate:

class AppDelegate: UIResponder, UIApplicationDelegate {
    ...

    func application(
        _ application: UIApplication,
        didReceiveRemoteNotification userInfo: [AnyHashable: Any],
        fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
    ) {
        print("Method called!")
        completionHandler(.noData)
    }
}

And here are a few payloads and headers that I tested. I tried all of the following payloads with the following headers in any combination.

  • apns-push-type=alert or apns-push-type=background
  • apns-priority=5 or apns-priority=10

Example 1: Visible notification

{
  "aps": {
    "alert": {
      "body": "Test"
    },
    "badge": 1,
    "content-available": 1
  },
  "test": "data"
}

Example 2: Silent notification without badge update

{
  "aps": {
    "content-available": 1
  },
  "test": "data"
}

Example 3: Silent notification with empty alert block and badge update, based on ideas from this thread

{
  "aps": {
    "alert": {},
    "badge": 0,
    "content-available": 1
  },
  "test": "data"
}

As I said, no matter whether my app is in the foreground or background, the method is never called. At the same time, the userNotificationCenter(_:willPresent:withCompletionHandler:) method of the UNUserNotificationCenterDelegate is called when the app is in the foreground. At this point, I am running out of ideas what I could possibly be doing wrong, so I hope someone else has an idea what else to try.

Post not yet marked as solved Up vote post of hoelska Down vote post of hoelska
2.8k views
  • As I am unable to edit my post: My first payload example is missing a "interruption-level": "active" in the "aps"` block.

Add a Comment

Replies

Have you tried on an actual device, rather than the simulator?

How are you sending the notifications? From an actual server, or using Xcode to send them locally?

  • I am sending the notification from my local server, meaning I send it to the api.sandbox.push.apple.com:443 from a PHP server running on my local machine. I did not test it on an actual device because the server is not online yet and, therefore, I cannot get the device token. But from what I found out, the method should be called in the simulator, at least with the app in the foreground.

Add a Comment

I am sending the notifications from my local server, meaning I send the notifications to the api.sandbox.push.apple.com:443 URL from a PHP server running on my local machine.

I now tested it on a real device and it is working there. Which is very nice but from what I read, it is supposed to work on the simulator as well. So your reply is kind of the solution, but before I mark it as such, I would love to have someone from Apple check in on this topic to maybe clarify, why this is not working in the simulator and, if it is not a bug or mistake on my side, add a note to the documentation of the method that it is not or might not be called in the simulator to save other developers from the frustration of thinking their code is wrong.

My understanding is that in the simulator you can simulate notifications by drag-dropping a suitable JSON file onto the simulator - or with some command-line that achieves the same thing. I don't know what you've read, but maybe it was referring to that functionality?

This is something that has changed over time and googling finds lots of old suggestions of how to do it that are probably redundant...

Yes and no. I think you can simulate notifications in the ways you said (which I didn't test), but it is possible to send notifications to the simulator by sending them to the above URL using the simulator's device token, just like you would do it for a real device and in production.

The strange thing about the simulator is: As I said, I tried adding the UNUserNotificationCenterDelegate and all of the methods there are called as expected. When the app is in the foreground while receiving a notification, it calls the userNotificationCenter(_:willPresent:withCompletionHandler:) and when opening the app by tapping on a notification it calls the userNotificationCenter(_:didReceive:withCompletionHandler:) method.

From all the tests I've done, the simulator is acting pretty much like you would expect a real device to. Really the only thing that does not work is the application(_:didReceiveRemoteNotification:fetchCompletionHandler:) method, which is never called.

  • this notification:

    { "aps": { "content-available": 1 }, "test": "data" }

    you can intercept in the method userNotificationCenter(_:willPresent:withCompletionHandler:) in the simulator?

Add a Comment

Hey I'm experiencing the exact same thing, didReceiveRemoteNotification is never called on a iOS 16.2 Simulators despite all the Notification methods being called. Same code (and notifications) work flawlessly on device. So close yet so far... ;)

I'm experiencing the same issue, but it also happens on a real iPhone. Not getting silent notification when it's a SwiftUI app. When I remove @main from struct App and put @main at AppDelegate, everything works like a charm. I think it's a bug in SwiftUI

It turned out to be a bug in Firebase Cloud Messaging. I've turned off method swizzling and it worked. Look up on the internet "Method swizzling in Firebase Cloud Messaging" on how to turn it off

Has anyone gotten this working? I'm seeing the same issue XCode 15.1 - didReceiveRemoteNotification will be called on a physical device but not in the simulator. Push notifications with content work on both.