SFSafariApplication::dispatchMessage() in xcode 16

We are making Safari extension for MacOS, that uses SFSafariApplication.dispatchMessage() to communicate between native and javascript parts of extension. Until recently everything worked, however after update to xcode 16 I started getting this error:

'dispatchMessage(withName:toExtensionWithIdentifier:userInfo:completionHandler:)' is unavailable in application extensions for macOS: Not available to extensions
'dispatchMessage(withName:toExtensionWithIdentifier:userInfo:completionHandler:)' has been explicitly marked unavailable here (SafariServices.SFSafariApplication)

I looked into documentation, however I did not find any hint of dispatchMessage() being replaced by something else. According to https://developer.apple.com/documentation/safariservices/messaging-between-the-app-and-javascript-in-a-safari-web-extension this is the way communication should be done.

Is it a bug? Or can someone direct me to working alternative of communication?

Answered by Frameworks Engineer in 804150022

The error you're seeing is because dispatchMessage(withName:toExtensionWithIdentifier:userInfo:completionHandler:) has always been unavailable for app extensions, which is now being flagged by the compiler in Xcode 16.

Communication from the extension to JavaScript is handled via context.completeRequest(returningItems:completionHandler:), but only in response to messages initiated from JavaScript. The dispatchMessage method is intended for use by the app itself—not the extension process—to initiate communication when the app is running.

Accepted Answer

The error you're seeing is because dispatchMessage(withName:toExtensionWithIdentifier:userInfo:completionHandler:) has always been unavailable for app extensions, which is now being flagged by the compiler in Xcode 16.

Communication from the extension to JavaScript is handled via context.completeRequest(returningItems:completionHandler:), but only in response to messages initiated from JavaScript. The dispatchMessage method is intended for use by the app itself—not the extension process—to initiate communication when the app is running.

Perhaps you can elaborate on what you are trying to do and there may be another solution @Kaven ?

The idea is:

  1. Javascript part of extension gathers urls from visited page, and sends them to native part

  2. The native part processes urls in the background (potentially longer running process)

  3. When url is processed, the native part of extension gives result back to javascript to show them. This is the place where I use dispatchMessage()

Both javascript and the native handling is in "Shared (Extension)" folder, if it plays some role. According to this: https://developer.apple.com/documentation/safariservices/messaging-between-the-app-and-javascript-in-a-safari-web-extension , dispatchMessage is the way to use ... and it worked in xcode 15.4

@Frameworks Engineer Well, I don't understand it. Here: https://developer.apple.com/documentation/safariservices/messaging-between-the-app-and-javascript-in-a-safari-web-extension it clearly says that that the native part should communicate to the javascript by dispatchMessage(). Or am I misunderstanding it? It worked in xcode 15.4.

I can't respond immediatelly to incoming message from javascript, because there is some processing to be done in the native part, and it can take some time.

For clarification, I am trying to communicate between javascript and swift part which are both in "Shared (Extension)" directory, and are part of "... Extension" target.

Got it working, @Frameworks Engineer set me on the right track. Only responding to messages from javascript is OK, because in native part I can store NSExtensionContext of incoming message, and use it for response asynchronously, even half a minute later. That was everything I needed.

@Kaven - would you mind posting how you are now getting the NSExtensionContext in your background js script? Are you listening on a port? I am trying to implement the communication between my js and swift code in my extension and running into the same problem.

SFSafariApplication::dispatchMessage() in xcode 16
 
 
Q