macOS: Remote push notification accepted by APNs (HTTP 200) but never displayed — application(_:didReceiveRemoteNotification:) fires instead of willPresent

I'm running a PoC to validate remote push notification delivery on macOS (AppKit, no Storyboard, programmatic setup) using UNUserNotificationCenter.

Environment:

  • macOS Version 26.5 (25F71)
  • Xcode Version 26.2 (17C52)
  • App: sandboxed, entitlements include aps-environment: development, Push Notifications + Background Modes (Remote notifications) capabilities enabled
  • Auth: token-based (.p8 key, ES256 JWT), sent via curl directly to api.sandbox.push.apple.com

Setup:

UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
    if granted { NSApplication.shared.registerForRemoteNotifications() }
}

Delegate implements both:

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)

and the legacy:

func application(_ application: NSApplication, didReceiveRemoteNotification userInfo: [String: Any])

Repro steps:

  • App launches, permission granted (true), device token successfully obtained via didRegisterForRemoteNotificationsWithDeviceToken
  • Local notifications (via UNNotificationRequest + UNTimeIntervalNotificationTrigger) work correctly — banner displays, willPresent fires as expected
  • Send a remote push via curl:
curl -v --header "apns-topic: $TOPIC" --header "apns-push-type: alert" \
  --header "authorization: bearer $AUTHENTICATION_TOKEN" \
  --data '{"aps": {"alert": {"title": "Test Title","body": "Test Body"}}}' \
  --http2 https://api.sandbox.push.apple.com/3/device/$DEVICE_TOKEN
  • APNs responds HTTP/2 200 with a valid apns-id — accepted successfully

Observed:

  • No banner appears on screen
  • Notification does not appear in Notification Center either
  • Console log shows application(_:didReceiveRemoteNotification:) fired with the correct payload
  • willPresent is never called for this remote push, despite firing correctly for local notifications in the same session

Question:

Given willPresent is documented to be the method responsible for foreground presentation decisions, and it's working correctly for local notifications, why would a remote alert-type push (with a proper alert dict, no content-available) route only through the legacy didReceiveRemoteNotification path and never reach willPresent/get displayed, despite a 200 response from APNs?

One thing I noticed while investigating: the App ID used for this app (auto-created by Xcode's automatic signing) lists its Platform as "iOS, iPadOS, tvOS, watchOS, visionOS" only — macOS is not checked, even though the app itself is macOS-only and Push Notifications capability shows as enabled. Could this platform scoping on the App ID be responsible for APNs/the OS accepting the push at the network layer but not treating it as "alert-UI eligible" for display? Is macOS required to be explicitly checked as a platform on the App ID for willPresent to be invoked correctly, or is that unrelated?

Any guidance on what determines whether a remote push is routed to the foreground presentation path vs. the legacy background delegate path on macOS would be appreciated.

macOS: Remote push notification accepted by APNs (HTTP 200) but never displayed — application(_:didReceiveRemoteNotification:) fires instead of willPresent
 
 
Q