There are various ways you can do this. Let me start by explaining the standard XPC way, and then we can talk about easier alternatives.
XPC implements a request/response protocol. When a client connects to your service, it issues a request and may optionally expect a response. This makes it hard for the service to unilaterally notify the client of events.
There are two ways to handle this within XPC:
Long polling
Reverse connection
Long polling is just like HTTP long polling: The client issues a request to the service and the service doesn’t respond until it has something meaningful for the client to hear about.
Like HTTP long polling, this is a bit of a hack and it’s not something I generally recommend.
In contrast, the reverse connection approach is more sophisticated. Here the client creates an anonymous listener (-
[NSXPCListener anonymousListener] [1]), gets an endpoint from that (
endpoint), and uses an XPC message to send that to the service. The service can then create a connection from that endpoint (
-[NSXPCConnection initWithListenerEndpoint:]). For this connection the service is the ‘client’, and thus it can issue requests.
There is one major gotcha here, namely denial of service (possibly deliberate, but more likely accidental). If the client stops processing requests from this reverse connection and the service keeps sending them, the requests will stack up in memory on the service side. Eventually the service will run out of memory and crash. Not good.
For this reason it’s important that the service not send unbounded requests to the client. A good way to handle this is to use a request/response pair, and wait for the response before sending any more requests.
Finally, for simple tasks it might be easier to use a different notification mechanism. For example, the service could simply post a Darwin notification (see the
<notify.h> man page) saying that something has changed. The client would then respond to that notification by using XPC to get the latest state from the service.
Oh, wait, one more thing.
NSProgress in XPC-transportable, so if you just want to get progress info (including finished notifications) you can use that.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"[1] I’m going to use
NSXPCConnection constructs here, although everything I talk about can also be done with the XPC C API.