Confused by new Swift XPC API's xpc_listener_t and xpc_session_t types

Hey!

I'm trying to create an XPC messaging feature between my daemon and main application.

I'm trying to use the new Swift low-level API available from macOS 14.0. The documentation is extremely confusing when looking at it from Swift:

The xpc_listener_t type

  1. Seems to be something I shouldn't use in the Swift API, and would rather have to use XPCListener.

  2. Also, it appears to have no public API other than the xpc_listener_set_peer_code_signing_requirement function. Which would make it impossible to create this type.

  3. However, when going into xpc.h, one can see that there is an API in fact:

    API_AVAILABLE(macos(14.0), macCatalyst(17.0))
    API_UNAVAILABLE(ios, tvos, watchos)
    XPC_EXPORT XPC_SWIFT_NOEXPORT XPC_RETURNS_RETAINED XPC_WARN_RESULT
    xpc_listener_t _Nullable
    xpc_listener_create(const char * service,
    	dispatch_queue_t _Nullable target_queue,
    	xpc_listener_create_flags_t flags,
    	xpc_listener_incoming_session_handler_t incoming_session_handler,
    	xpc_rich_error_t _Nullable * _Nullable error_out);
    

    which is a very unusual declaration - the first parameter for example shows up as Int8 type in Swift. Not to mention I haven't been able to create the next parameter, xpc_listener_create_flags_t at all, even though it seems to be a UInt64-based flag based on the C declaration, but passing UInt64(0) throws a compiler error. It really seems like something I shouldn't use from Swift.

  4. But then again, the extremely important security-related API mentioned above, xpc_listener_set_peer_code_signing_requirement can only take an xpc_listener_t object as a parameter, not an XPCListener type.

  5. There seems to be no conversion available between the two. However the documentation in the XPC framework seems to be telling the story of these two types being very equal, because of the following:

The xpc_session_t type

  1. seemingly again has only deprecated methods mostly, the important one staying behind is xpc_session_set_peer_code_signing_requirement.
  2. However, this would again require the creation of an xpc_session_t object, for which in the XPC framework one will find declarations like:
    @available(macOS, introduced: 13.0, deprecated: 14.0, renamed: "XPCSession")
    @available(macCatalyst, introduced: 16.0, deprecated: 17.0, renamed: "XPCSession")
    @available(iOS, unavailable)
    @available(tvOS, unavailable)
    @available(watchOS, unavailable)
    public typealias xpc_session_t = OS_xpc_object
    
    plus basically all API of XPCSession being originally declared as xpc_session_* APIs and all of them having deprecated: 14.0, renamed: * marks. This is telling me xpc_session_t and XPCSession are in fact the same/same-ish.
  3. But again, there is seemingly no conversion between these two types. Which brings me to again being unable to create a code signing requirement for the XPCSession object.

I've read some older forum posts, and I saw Apple Engineers admitting the code signing requirement APIs are missing from the new Swift APIs, however they seem to have been added in macOS 14.4 - although it appears to have been mistakenly added to the C-family functions, which have not been exposed to Swift correctly, because they still use the deprecated xpc_listener_t and xpc_session_t types.

So my question is: what is going on here? :) Making XPC connections without a code signing requirement in 2025 seems like a no-go, so do I have to still stick with C - even though this new API seems to be focused on Swift?

Answered by DTS Engineer in 855490022

Lemme see if I have this straight:

  • You want to use the new Swift XPC API for app-to-daemon XPC communication.
  • You want the daemon to validate the code signature of the client.

Is that right?

If so, the source of your confusion is that currently shipping systems have no support for this. Fortunately, that seems to have changed in macOS 26 (currently in beta). See Validating Signature Of XPC Process.

Share and Enjoy

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

Lemme see if I have this straight:

  • You want to use the new Swift XPC API for app-to-daemon XPC communication.
  • You want the daemon to validate the code signature of the client.

Is that right?

If so, the source of your confusion is that currently shipping systems have no support for this. Fortunately, that seems to have changed in macOS 26 (currently in beta). See Validating Signature Of XPC Process.

Share and Enjoy

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

Thank you, it is nice to know these Swift-based CSR APIs are coming in macOS 26.0.

However, I'm still wondering what these two functions are:

  • xpc_session_set_peer_code_signing_requirement
  • xpc_listener_set_peer_code_signing_requirement

Because they are new in macOS 14.4, but seem to have basically zero use in Swift as per above.

xpc_listener_t and xpc_session_t seem to be completely new objects from macOS 13.0, however the xpc C API - the convention they seem to follow - is way older. The two objects mentioned however gained a full set of new functions in macOS 13.0 and 14.0.

E.g.:

  • xpc_listener_create is a macOS 14.0+ function
  • xpc_session_create_mach_service is a macOS 13.0+ function

How am I supposed to treat these compared to the old C API using xpc_connection_create_mach_service + either XPC_CONNECTION_MACH_SERVICE_PRIVILEGED or XPC_CONNECTION_MACH_SERVICE_LISTENER? Are they supposed to be an easier-to-use session based API?

but seem to have basically zero use in Swift as per above.

These are part of XPC’s low-level C API (using the terms from XPC Resources). You can call this from Swift, just like you can call malloc from Swift, but the NSXPCConnection and low-level Swift APIs are both nicer.

Are they supposed to be an easier-to-use session based API?

The new session-based APIs were designed to provide a better model for XPC, one that’s more closely aligned with the reality of the underlying implementation. They were introduced around the same time as the low-level Swift API, and so that API only supports this model. The low-level C API has to support this model and the previous model for compatibility.

Share and Enjoy

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

Confused by new Swift XPC API's xpc_listener_t and xpc_session_t types
 
 
Q