---
title: "TN3113: Testing and debugging XPC code with an anonymous listener"
framework: technotes
role: article
role_heading: Article
path: technotes/tn3113-testing-xpc-code-with-an-anonymous-listener
---

# TN3113: Testing and debugging XPC code with an anonymous listener

Use an anonymous XPC listener to simplify your XPC testing and debugging.

## Overview

Overview Testing and debugging XPC code is tricky because there are two processes involved.  Imagine you have an app with an embedded XPC service.  To debug this you have to run two instances of the debugger, one connected to the app and another to the service, and then switch between them.  This works, but it’s quite inconvenient.  Fortunately there is a better way, a technique that allows you to test and debug all your XPC code in a single process. important: This technique does not help with all XPC testing and debugging scenarios.  For example, if you’re developing a launchd daemon that performs privileged operations on behalf of your app, you can’t use this technique to debug your privileged code because it’s not running in a privileged process.  However, even in situations like that, this technique is useful when debugging your XPC-specific code.  For example, you might use it to create a unit test for your NSSecureCoding implementation. This technique involves two key concepts: Put your XPC listener and XPC client code in the same test program.  The specifics of this program are up to you: It might be a simple test app that you create specifically for this purpose, or it might be an Xcode unit test bundle, or it might be some other kind of program. Use an anonymous XPC listener to connect your XPC listener and client code. Imagine you’re building an app with an embedded XPC service.  You have a MyListener class that manages your XPC listener within the XPC service, and a MyConnection class that manages the connection on the app side of things.  Add both of those classes, and all their support code, to your test program.  Then change MyListener to accept an NSXPCListener instance.  For example, your MyListener class might look like this: class MyListener {

init() {         self.listener = NSXPCListener.service()     }

let listener: NSXPCListener          … more code … } note: While this example uses the Foundation XPC API, the same technique works for the low-level C XPC API. Change its initialiser to look like this: init(listener: NSXPCListener = .service()) {     self.listener = listener } This uses the XPC service’s listener by default, but allows you to override that by passing in a value to the listener parameter. Now, in your test program, call anonymous() to create a anonymous listener and pass that to your listener abstraction: let myListener = MyListener(listener: .anonymous()) On the client side, your MyConnection class might look like this: class MyConnection {

init() {         self.connection = NSXPCConnection(serviceName: "com.example.MyService")     }

let connection: NSXPCConnection } Change the initialiser to look like this: init(connection: NSXPCConnection = .init(serviceName: "com.example.MyService")) {     self.connection = connection } This sets up a connection to the XPC service’s listener by default, but allows you to override that by passing in a value to the connection parameter. Finally, in your test program, use init(listenerEndpoint:) to create a connection to your anonymous listener: let connection = NSXPCConnection(listenerEndpoint: myListener.listener.endpoint) let myConnection = MyConnection(connection: connection) You now have an XPC connection between your client code and your listener, with all the code running in the same test program.  This makes it much easier to debug your XPC code.  And the same technique is perfect for unit tests. Revision History 2022-04-12 Added syntax highlighting to the code listings (r. 89366505). 2022-02-08 Republished as TN3113.  Expanded the introduction to clarify the overall concept.  Made other minor editorial changes. 2021-11-09 First published as ”Testing and Debugging XPC Code With an Anonymous Listener” on Apple Developer Forums.

## See Also

### Latest

- [TN3210: Optimizing your app for iPhone Mirroring](technotes/tn3210-optimizing-your-app-for-iphone-mirroring.md)
- [TN3211: Resolving SwiftUI source incompatibilities for State and ContentBuilder](technotes/tn3211-resolving-swiftui-source-incompatibilities-for-state-and-contentbuilder.md)
- [TN3212: Adopting gesture recognizers for Sidecar touch support](technotes/tn3212-adopting-gesture-recognizers-for-sidecar-touch-support.md)
- [TN3208: Preparing your app’s launch screen to meet App Store requirements](technotes/tn3208-preparing-your-apps-launch-screen-to-meet-app-store-requirements.md)
- [TN3205: Low-latency communication with RDMA over Thunderbolt](technotes/tn3205-low-latency-communication-with-rdma-over-thunderbolt.md)
- [TN3206: Updating Apple Pay certificates](technotes/tn3206-updating-apple-pay-certificates.md)
- [TN3179: Understanding local network privacy](technotes/tn3179-understanding-local-network-privacy.md)
- [TN3190: USB audio device design considerations](technotes/tn3190-usb-audio-device-design-considerations.md)
- [TN3194: Handling account deletions and revoking tokens for Sign in with Apple](technotes/tn3194-handling-account-deletions-and-revoking-tokens-for-sign-in-with-apple.md)
- [TN3193: Managing the on-device foundation model’s context window](technotes/tn3193-managing-the-on-device-foundation-model-s-context-window.md)
- [TN3115: Bluetooth State Restoration app relaunch rules](technotes/tn3115-bluetooth-state-restoration-app-relaunch-rules.md)
- [TN3192: Migrating your iPad app from the deprecated UIRequiresFullScreen key](technotes/tn3192-migrating-your-app-from-the-deprecated-uirequiresfullscreen-key.md)
- [TN3151: Choosing the right networking API](technotes/tn3151-choosing-the-right-networking-api.md)
- [TN3111: iOS Wi-Fi API overview](technotes/tn3111-ios-wifi-api-overview.md)
- [TN3191: IMAP extensions supported by Mail for iOS, iPadOS, and visionOS](technotes/tn3191-imap-extensions-supported-by-mail.md)
