Establishing an NSXPCConnection from a Finder Sync Extension to an XPC Service

I am currently building a sandboxed app that also contains:

  • Finder Sync Extension (sandboxed)
  • XPC Service (sandboxed)


The XPC Service exists to facilitate communication between the host app and the Finder Sync extension.


So far, I have succesfully established an NSXPCConnection from the host app to the XPC service and was able to invoke a method on the XPC service from the host app. However, when I try to create a similar connection upon instantiation of the principal class of the Finder Sync extension, I immediately receive an error saying that the connection to the service was invalidated. I have confirmed that the XPC service is running, but somehow the connection is still invalidated immediately. I am also using the exact same service name when establishing the connection from the host app and when doing the same thing from the Finder Sync Extension.


  • What could be the reason that the NSXPCConnection is invalidated immediately?
  • Is there some kind of sandbox restriction at play here?
  • Is communicating throught an XPC Service the recommended IPC architecture for a sandboxed app to communicate with an embedded Finder Sync Extension?

Accepted Reply

The XPC Service exists to facilitate communication between the host app and the Finder Sync extension.

The problem here is that app-based XPC Services are scoped to the app that contains them, and you have two apps in play (well, your Finder Sync extension is an app extension, but it behaves like an app in this regard). Thus, if you put your XPC Service inside your app, it can only be seen by your app. And if you put your XPC Service inside your app extension, it can only be seen by your app extension.

The standard way out of the conundrum is to use an XPC login item for this shared state. Due to an accident of how these are implemented, they are visible to both your app and your app extension. For an example of such a login item, see AppSandboxLoginItemXPCDemo.

This approach is ideal if your Finder Sync extension needs a persistent presence, which is pretty common. However, if your Finder Sync extension needs to share state but does not need the code sharing that state to be running all the time, this is clearly suboptimal. If that’s the case then I recommend that you file enhancement request requesting a way to share this state without the login item.

If you do file a bug, please post the bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

The XPC Service exists to facilitate communication between the host app and the Finder Sync extension.

The problem here is that app-based XPC Services are scoped to the app that contains them, and you have two apps in play (well, your Finder Sync extension is an app extension, but it behaves like an app in this regard). Thus, if you put your XPC Service inside your app, it can only be seen by your app. And if you put your XPC Service inside your app extension, it can only be seen by your app extension.

The standard way out of the conundrum is to use an XPC login item for this shared state. Due to an accident of how these are implemented, they are visible to both your app and your app extension. For an example of such a login item, see AppSandboxLoginItemXPCDemo.

This approach is ideal if your Finder Sync extension needs a persistent presence, which is pretty common. However, if your Finder Sync extension needs to share state but does not need the code sharing that state to be running all the time, this is clearly suboptimal. If that’s the case then I recommend that you file enhancement request requesting a way to share this state without the login item.

If you do file a bug, please post the bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Ahh, thank you. Your response so far has been the most clear explanation I have seen on the web as to why this architecture is not possible. I do have a follow up question:


If I were to use an XPC Login Item, would that then require us to explicitly request with the user to allow the XPC Service to launch on login? In our app, the user will choose with folder on their OS contains items they would like to sync. Would their action of choosing to sync items in a folder qualify as allowing the XPC Service to launch on login? Or will that need to be in a separate prompt?

If I were to use an XPC Login Item, would that then require us to explicitly request with the user to allow the XPC Service to launch on login?

Is this a technical question? Or a policy question? It seems like a policy question — specifically related to clause 2.4.5 (iii) of the App Store Review Guidelines — and, I’m sorry but, I can’t answer those.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Ahh, fair enough. Thanks again for your time.

Thanks for posting.
I am still facing the same issue.
My app build contains extensions and xpc as follow:
  • Finder Sync Extension (sandboxed)
 - XPC Service (not sandboxed)

For an example of such a login item, see AppSandboxLoginItemXPCDemo.

I've applied this example but It also doesn't work. And I don’t think this cause because XPC service is not sandboxed.
  • do you have good experience with this recently?

  • Is there a updated way for a communication between xpc and finder sync extension? 

My app build contains extensions and xpc as follow:

This won’t work. There is no way to share state between your app and a Finder Sync appex using a standard XPC Service. This is because your XPC Service is only ‘visible’ to its container app (or appex). So:
  • If you place your XPC Service in your app’s bundle, the app can see it but the appex can’t.

  • If you place your XPC Service in your appex’s bundle, the appex can see it but the app can’t.

The only way out of this conundrum is a Service Management login item. This is visible to both the app and the appex.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
  • How can we use login item, since there are no template target for it now in Xcode 13. The demo's login item seem to be a mix of bundle target and app target. And I try to create one and modify as the one in the demo, still not working as a login item.

Add a Comment

The demo's login item seem to be a mix of bundle target and app target.

Oh, wow, that’s weird. The AppSandboxLoginItemXPCDemo sample code uses a bundle target but then set the Mach-O Type build setting (MACH_O_TYPE) to Executable (mh_execute). That’s… well… an interesting choice. It would be better to just start with an app target (New > Target > macOS > App). That’s what I normally do and it works just fine.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"