What is an XPC Service? How can it benefit my app? Should I use one? Remotion uses an XPC service to overlay shared content. It's where we render cursors, drawing, and more:
Why we decided to use XPC
At Remotion, we're building on the Zoom Video SDK, which is known for its reliability and high performance. The SDK includes an optimization that detects if shared content is being occluded by Remotion.app, and if it is, it does not send any frames. While in most cases, this saves on user CPU and bandwidth, it prevented us from drawing cursor events, such as clicks or drawings, into an overlay over the shared content. We worked around this issue by rendering our overlay in a separate process.
Secondly, macOS will only allow overlaying a window over a full screen application if the window is owned by an application with
NSApplication.ActivationPolicy set to
.accessory. Since we allow our users to use the app in
.regular mode, separating the overlay from the main app saves us from having to dynamically update the activation policy when overlaying full screen apps.
What is an XPC Service?
Let's begin by discussing what an XPC service is. XPC Services is an API provided by Apple that enables simple interprocess communication. We use this API to create XPC services: tools that run on different processes and can perform work on behalf of our app.
XPC Services advantages
XPC services are effective tools for diagnostic reporting, helper functions (such as machine learning, editing, and rendering), and for working around limitations in third-party libraries. A helpful side effect of XPC services is that if the external process crashes, it won't affect your host process. Whether this is advantageous or not depends on the situation, but it's worth noting.
XPC Services limitations
XPC services have one major limitation: they do not accept user interaction. This may be a deal breaker for you. You can use an external process to show UI. The external process can have its own window hierarchy and use SwiftUI, but the user cannot interact with anything in the external process. UI elements such as buttons or sliders will not accept mouse or keyboard events.
How to create an XPC Service connection
If you are reading this and have no idea how to create an XPC service, don't worry! Let's quickly go over how to establish an XPC service connection.
1. Set up the Info.plist
You'll need to alter the Info.plist for your external process. For more information, run
man xpcservice.plist in Terminal. Here is an example of our plist:
We need to call window APIs like
CGWindowListCopyWindowInfo, so we set
true. See this Apple Developer Forum Post for more detail on why.
We need to call main thread APIs to render UI, so we set
2. Create the protocol
Next, decide what this service will do by creating a protocol. Note that both the host process and the external process will need to reference this protocol. Put this protocol in a package that is shared by both processes.
3. Create the exported object
Our main process will interact with external process through something called the exported object. This object implements the protocol we have defined and provides the actual behavior for the service. The service "exports" it to make it available to the process hosting the service over an NSXPCConnection. Create this object in the external process.
4. Create the service delegate
This essentially functions as “main” for your external process. This sets up the bridge between the host process and the external process.
5. Create the connection
Inside your main process, create a manager responsible for starting, using, and stopping the NSXPCConnection. This is created in the host process.
6. Use the XPC Service in your main process
Now that you have all the components, it’s time to use it in your host process!
Although it has its limitations, we found the XPC Services API to be very helpful in navigating around the Zoom Video SDK. Once you understand how simple it can be to leverage XPC services, it opens up many doors for other ways to use it.
Let us know what you think! In what cases have you found XPC services to be helpful?
Learn more about XPC Services in Apple's official documentation: