Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NotificationService Extension didReceive Not Called in iOS Simulator with xcrun simctl push

NotificationService Extension didReceive Not Called in iOS Simulator with xcrun simctl push

I’m working on an iOS app with a Notification Service Extension to modify push notification content. The extension’s didReceive(_:withContentHandler:) method isn’t being called when I send a notification using xcrun simctl push in the simulator, even though the notification appears. I’ve confirmed the payload includes "mutable-content": 1, and the extension is embedded in the app, but I see no console output or evidence the extension is triggered.

Here’s my setup:

  • App Bundle ID: com.domain.dev
  • Extension Bundle ID: com.domain.dev.NotificationServiceExtension
  • Testing Environment: iOS Simulator (e.g., iPhone 15, iOS 18.0)
  • Command:
xcrun simctl push booted com.domain.dev notification.json
  • Payload (notification.json):
{
  "aps": {
    "alert": {
      "title": "Test Notification",
      "body": "This is a test push notification."
    },
    "mutable-content": 1
  },
  "customData": {
    "key": "value"
  }
}
  • NotificationService.swift:
import UserNotifications

class NotificationService: UNNotificationServiceExtension {
    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?

    override init() {
        super.init()
        print("NotificationService: Extension initialized at \(Date())")
    }

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        print("NotificationService: didReceive called with request: \(request)")
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        if let bestAttemptContent = bestAttemptContent {
            bestAttemptContent.title = "\(bestAttemptContent.title) [Modified]"
            contentHandler(bestAttemptContent)
        } else {
            contentHandler(request.content)
        }
    }

    override func serviceExtensionTimeWillExpire() {
        print("NotificationService: Time will expire")
        if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }
}

What I’ve Tried:

  1. Verified "mutable-content": 1 in the payload.
  2. Ensured the extension is embedded in the app target under “Frameworks, Libraries, and Embedded Content” with “Embed & Sign”.
  3. Added logging in init() and didReceive, but no output appears in the Xcode console.
  4. Ran the extension scheme directly in the simulator—init() logs, but didReceive doesn’t when sending the push.
  5. Cleaned and rebuilt the project multiple times.
  6. Checked bundle IDs and deployment targets (both set to iOS 12.0 or higher).
  7. Attached the debugger to the extension process, but it doesn’t show up unless I run the extension scheme manually.
  8. Confirmed the .appex file exists in the simulator’s PlugIns folder via xcrun simctl get_app_container.

Observations:

  • The notification shows in the simulator, but without the [Modified] title, indicating the extension isn’t processing it.
  • No crash logs or errors in the console.
  • I haven’t tested on a real device yet due to current focus on simulator debugging.

Questions:

  • Why isn’t didReceive(_:withContentHandler:) called when using xcrun simctl push in the simulator?
  • Is this a limitation of the simulator or xcrun simctl push with Notification Service Extensions?
  • What else can I check or configure to make this work in the simulator?

What I Expect
I expect the NotificationService extension to intercept the push notification, modify the title (e.g., append [Modified]), and display the updated content in the simulator. Ideally, I’d see the print statements in the console confirming the extension is running and processing the request.

Additional Info

  • Xcode Version: [e.g., 16.0]
  • iOS Simulator Version: [e.g., 18.0]
  • No App Groups are currently configured—could this be required?
like image 899
Vishal Kale Avatar asked Dec 01 '25 10:12

Vishal Kale


1 Answers

Xcode 11.4 release notes mention mutable-content doesn't work for xcrun simctl push:

Notification Service Extensions do not work in simulated push notifications. The mutable-content key is not honored. (55822721)

Unfortunately, it seems like this is still the case.

Xcode 14 release notes mention sending remote notifications to the simulator as an alternative, noting that Notification Service Extensions still don't work for simctl push:

Simulator now supports remote notifications in iOS 16 when running in macOS 13 on Mac computers with Apple silicon or T2 processors. Simulator supports the Apple Push Notification Service Sandbox environment. Your server can send a remote notification to your app running in that simulator by connecting to the APNS Sandbox (api.sandbox.push.apple.com). Each simulator generates registration tokens unique to the combination of that simulator and the Mac hardware it’s running on. See User Notifications for more information.

Remote Notifications support more features (like Notification Service Extensions) than locally simulated notifications using .apns payload files or the simctl push command.

This works for me. I'm sending to the simulator using the Push Notifications Console.

like image 111
DJ Tarazona Avatar answered Dec 03 '25 00:12

DJ Tarazona



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!