Compile Failure on NSXPCInterface Initializer

I have a project that leverages XPC and has interoperability between Swift and Objective-C++. I am presently getting a compile-time error in one of our unit test targets, of "Argument passed to call that takes no arguments" on the following code:

let interface = NSXPCInterface(with: XPCServiceDelegate.self)

My XPCServiceDelegate protocol is defined as:

@objc(XPCServiceDelegate) public protocol XPCServiceDelegate {
    //...
}

For the longest time, this code has compiled successfully, and it has not recently changed. There are two confusing things about this error. The first is that I have a different build scheme that will compile correctly other code with the same structure. The other is that I have team members that are able to compile my failing scheme successfully on the same XCode version, OSVersion, and branch of our repository.

I've attempted numerous things to try to get this code to compile, but I've run out of ideas.

Here's what I've tried:

  • Clean build both on XCode 16.4 and XCode 26 Beta
  • Delete DerivedData and rebuild on XCode 16.4 and XCode 26 Beta
  • Delete and re-clone our git repository
  • Uninstall and reinstall XCode
  • Attempt to locate cached data for XCode and clear it out. (I'm not sure if I got everything that exists on the system for this.)
  • Ensure all OS and XCode updates have been applied.

The interface specification for NSXPCInterface clearly has an initializer with one arguement for the delegate protocol, so I don't know why the compiler would fail for this. Is there some kind of forward declaration or shadowing of NSXPCInterface? Do you have any ideas on what I could try next?

Well, that’s weird.

I can’t see anything wrong with your basic approach. This is gonna require some digging.

First up, if you split that line into two:

let proto = XPCServiceDelegate.self
let interface = NSXPCInterface(with: proto)

does the error persist? I suspect it will, and that it’ll show up on the second line, but I want to confirm that.

Share and Enjoy

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

@DTS Engineer, the error does persist when I separate the protocol into the local variable.

The error appears on the initialization lines for NSXPCInterface:

OK. That’s kinda what I expected, but it’s good to be sure.

This is still weird. I think your “forward declaration” theory is a thread worth pulling on, that is, someone is overriding the declaration of NSXPCInterface in some way.

Let’s try to rule out a straightforward conflict. If you qualify the name with the Foundation module, does that change things?

let interface = Foundation.NSXPCInterface(with: proto)

Share and Enjoy

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

@DTS Engineer, I'm still getting the issue even with the Foundation module qualifier in the front of NSXPCInterface.

The strangest thing is that I have others on my team that can build successfully with the same commit on the same version of XCode. I suspect something more environmental to my machine.

I noticed that when I Jump to Definition on NSXPCInterface, XCode sometimes points me to the Swift definition of the interface, like below:

@available(macOS 10.8, *)
open class NSXPCInterface : NSObject {

    public /*not inherited*/ init(with protocol: Protocol)

    unowned(unsafe) open var `protocol`: Protocol

    //...
}

and other times it will point me to NSXPCConnection.h, like below:

API_AVAILABLE(macos(10.8), ios(6.0), watchos(2.0), tvos(9.0))
@interface NSXPCInterface : NSObject

// Factory method to get an NSXPCInterface instance for a given protocol. Most interfaces do not need any further configuration. Interfaces with collection classes or additional proxy objects should be configured using the methods below.
+ (NSXPCInterface *)interfaceWithProtocol:(Protocol *)protocol;

// The Objective C protocol this NSXPCInterface is based upon.
@property (assign) Protocol *protocol;

//...
@end

Also, the Autocomplete shows the Initializer with the protocol labeled argument and not with. I attempted changing to use "protocol" for the label, but that's not working either.

Thanks for running that test.

I suspect something more environmental to my machine.

Right, but the question is whether to debug this from ‘above’ or ‘below’.

So, speaking of ‘below’, let’s try this test: If you create a new user account on your Mac and try to build the project there, does it have the same problem?

If it does, that means there’s something going on with your system as a whole. If it doesn’t, that means it’s tied to your user account.

Share and Enjoy

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

@DTS Engineer, I created a secondary user account on my machine and I am receiving the same build errors.

a secondary user account on my machine [is] receiving the same build errors.

Oh, interesting. That was not the answer I was expecting. But, hey, that’s why we run tests.

But it does put me in a bit of a pickle because I’m short on ideas for how to debug this from ‘above’.

But not complete out of ideas yet (-:

My understanding is that this problem only shows up in your unit test target. If you gut your unit test — that is, remove all source files from it — can you get it to build?

If so, then add back a single source file with code like this:

import Foundation

@objc protocol XPCServiceDelegate { }

func doNothing() {
    let proto = XPCServiceDelegate.self
    let interface = NSXPCInterface(with: proto)
    print(interface)
}

Does that compile?


Oh, one quick check: You’re not using an installed toolchain are you? In Xcode, check if there’s an Xcode > Toolchains menu and, if there is, make sure the Xcode built-in one is chosen.

Share and Enjoy

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

I believe I am using the default toolchain. I do not see a Toolchains section in my XCode menu, and when I check my command line tools, it is set to XCode 16.4 (16F6).

If I remove all source files, it builds successfully. When I add the single file with the doNothing function, it fails. However, I'm getting a slightly different error this time:

Cannot convert value of type '(any XPCServiceDelegate).Type' to expected argument type 'Protocol'

If I specify the type of proto as Protocol, I get the error:

Cannot convert value of type 'ObjectiveC.`Protocol`' to expected argument type '__ObjC.`Protocol`'

@DTS Engineer, for my unit test target I have SWIFT_OBJC_INTEROP_MODE = objcxx. This is required for some of the files we import from our target under test. In the single file case above, if I remove this build setting, it's building fine.

Well, that’s interesting. I’ve seen a raft of weird problems with C++ interop, but this specific one doesn’t ring any bells. And it’s still weird that you only see it on one machine.

I tried reproducing this with a simple test project here in my office — using both XCTest and Swift Testing — and couldn’t. But that’s not a big surprise because of the above-mentioned mystery.

The next step is to start gutting your main app. That’ll either reveal more interesting info about what’s triggering the problem, or it’ll get you to a small test project that you can share with us for further analysis.

Share and Enjoy

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

Compile Failure on NSXPCInterface Initializer
 
 
Q