Post

Replies

Boosts

Views

Created

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?
12
0
202
Aug ’25
launchd Configuration for LaunchDaemon Spawning Processes in Both system and gui/<uid> Domains
I'm attempting to root-cause analyze issues I've been having with launch daemons controlled by launchd. My product has a single privileged LaunchDaemon running in the system domain (supposed to at least). I was looking at a client's machine that, for some reason, was running the daemon process both in the system domain and the gui/ domain for the logged in user. When I would kill both processes on the client machine, both of them would start right back up in their respective domains. The associated plist for this daemon process only exists in /Library/LaunchDaemons. My question is, how can this be possible that launchd would spin up multiple privileged daemons, but one of them running in the gui/ domain? How can this be prevented from happening? Some context/details: It was observed on the client's machine that the daemon service was previously disabled. The service was manually re-enabled using: launchctl enable system/<nameOfDaemon> sudo launchctl enable system/<nameOfDaemon> The daemon was reloaded by using: sudo launchctl load /Library/LaunchDaemons/<plist of daemon process>
0
0
613
Apr ’23
XPC Connection Not Invalidated on NSXPCListenerDelegate Denial
I am attempting to understand the expected behavior of several points related to XPC. Mainly, I have the following questions: Should I expect that NSXPCConnection.remoteObjectProxyWithErrorHandler to call the error handler if the associated NSXPCListenerDelegate returns false in its listener function? Does the error handler get called immediately if the remoteObjectProxyWithErrorHandler function fails? What does remoteObjectProxy return if an actual proxy object is never exported on the service-side (in the listener function)? Should I expect that NSXPCConnection.invalidate() and/or the connection's invalidationHandler to be called when the associated NSXPCListenerDelegate returns false in its listener function? According to the listener documentation below, it appears the listener function is supposed to invalidate the connection; however, I am not seeing this be the case. https://developer.apple.com/documentation/foundation/nsxpclistenerdelegate/1410381-listener To reject the connect, return a value of false. This causes the connection object to be invalidated. I have written a test that exhibits the fact when the listener function returns false, rather than the invalidationHandler being called, the interruptionHandler is called. import XCTest final class InvalidateTest: XCTestCase {   func testConnectionIsInvalidatedOnListenerRejection() {     //set up anonymous XPC Listener     let listener = NSXPCListener.anonymous()     let listenerDelegate = MockListenerDelegate()     listener.delegate = listenerDelegate     listener.resume()           //establish connection to service     let clientConnection = MockConnection(listenerEndpoint: listener.endpoint)     var interruptHandlerCalled = false     var invalidateHandlerCalled = false     let interruptionHandler = { interruptHandlerCalled = true }     let invalidationHandler = { invalidateHandlerCalled = true }     clientConnection.interruptionHandler = interruptionHandler     clientConnection.invalidationHandler = invalidationHandler     clientConnection.remoteObjectInterface = NSXPCInterface(with: XPCServDelegate.self)     clientConnection.exportedInterface = NSXPCInterface(with: XPCCliDelegate.self)     clientConnection.exportedObject = XPCCDelegate()     clientConnection.resume()           // get the proxy delegate to make the XPC pulse call     guard let proxy = clientConnection.remoteObjectProxy() as? XPCServDelegate else {       XCTAssert(false, "Unable to get proxy object")       return     }     // why is it not failing to get a proxy object in this case?           // make the pulse call     var replyCalled = false     let semaphore = DispatchSemaphore(value: 0)     proxy.pulse(reply: {       replyCalled = true       semaphore.signal()     })           let waitResult = semaphore.wait(timeout: .now() + 1)     XCTAssertEqual(waitResult, .timedOut)     XCTAssertFalse(replyCalled)           // why do these assertions fail?     XCTAssertTrue(clientConnection.invalidateCalled)     XCTAssertTrue(invalidateHandlerCalled)     XCTAssertFalse(interruptHandlerCalled)   } } @objc public protocol XPCServDelegate {   func pulse(reply: @escaping () -> Void) } class XPCSDelegate : XPCServDelegate {   func pulse(reply: @escaping () -> Void) {     reply()   } } @objc public protocol XPCCliDelegate {} class XPCCDelegate : XPCCliDelegate {} fileprivate class MockConnection : NSXPCConnection {   var invalidateCalled = false       override func invalidate() {     invalidateCalled = true     super.invalidate()   } } fileprivate class MockListenerDelegate : NSObject, NSXPCListenerDelegate {   func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {     return false   } }
0
0
1.7k
Nov ’22
Exception While Dynamically Cloning Object with an Enum setValue
I am attempting to dynamically clone a class object in Swift using reflection and the setValue function. This class contains an enum property that is backed with an Int, which is causing this dynamic reflection to crash: @objc enum Status : Int { case green case yellow case red } @objc class State : NSObject { @objc var status : Status init(_ status: Status) { self.status = status } } func testReflectiveClone() { let state1 = State(.green) let state2 = State(.yellow) let state1Mirror = Mirror(reflecting: state1) for property in state1Mirror.children.enumerated() { let label = property.element.label state2.setValue(property.element.value, forKey: label!) //crashes here } } This test function is throwing the following error in XCode: -[__SwiftValue longLongValue]: unrecognized selector sent to instance 0x600001e5a340 (NSInvalidArgumentException) Is it even possible to dynamically set enum values? What modification would I need to make to get this to work?
1
0
734
May ’22
Could not find module for target 'arm64-apple-macos'; found: x86_64, x86_64-apple-macos
I have an XCode Workspace that builds a product as a universal binary for Intel and Apple Silicon. On an Intel-based machine, I am attempting to import a Swift Package dependency by accessing a private git repository. When I attempt to import my dependency into my code and build, I'm getting the following error: Could not find module '<swift package name>' for target 'arm64-apple-macos'; found: x86_64, x86_64-apple-macos The project has Standard Architectures set for the ARCHS build setting and ONLY_ACTIVE_ARCH = NO. When I switch ONLY_ACTIVE_ARCH = YES, it builds fine. Is there a way to instruct the compiler to build the swift package dependency as universal and resolve this issue?
1
0
3k
Dec ’21
Can a Launch Daemon Communicate with Concurrent XPC Connections Configured with Different Interfaces
I have a use case in which I have a launch daemon (as the XPC service) than needs to communicate with two XPC clients. Each of these clients has different functional cases for communication that do not overlap. Therefore, the NSXPCInterface for client A would be configured with a different protocol than the NSXPCInterface that would be configured for client B. Client A and Client B do not need to talk to each other; they each just need to communicate with the daemon. I am confused how to appropriately set up the NSXPCListener and NSXPCListenerDelegate on the daemon to support NSXPCConnections with proxy objects that adhere to varying interfaces to support these two clients. Is there a way for a single NSXPCListener (and associated delegate) to listen for connections requiring the exportedInterface to be different? Is there a way to send data through the NSXPCConnection that will allow the NSXPCListenerDelegate to conditionally determine which exported interface and object to configure? One idea I had was to have the daemon contain two NSXPCListeners. Each listener would be responsible for connections coming from the respective clients. Will this option work? If so, it is the advisable approach?
1
0
1.1k
Dec ’21
Multiple NSXPCConnections, Invalidation, and Reconnection to launchd-managed service
I have small integration test that is confirming behavior in XPC communications (leveraging NSXPCConnection) between a dummy XPC service and an XPC client. My test is flaky, which is indicating to me that I don't fully understand the nature of connections between services and clients, and I was hoping to get clarity as to what's happening in my test. My test involves the following steps. XCode Pre-Action: Load the plist for a dummy XPC service into launchctl. Create 2 XPC client objects (in the same client process), each with their own NSXPCConnection to the dummy service, and connect. Tell client 1 to disconnect, which calls NSXPCConnection.invalidate() Using client 2, send a message to the same dummy XPC service over it's own NSXPCConnection object. Wait for the echo response from the dummy XPC service XCode Post-Action: Unload the plist for the dummy XPC service from launchctl    func testMultipleConnections() {     let delegate1 = MockClientDelegate()     let delegate2 = MockClientDelegate()     let client1 = XPCMessagingClientFacade(withServiceName: serviceName, andXPCErrorHandler: {error in })     let client2 = XPCMessagingClientFacade(withServiceName: serviceName, andXPCErrorHandler: {error in })     client1.processMessageDelegate = delegate1     client2.processMessageDelegate = delegate2           _ = client1.connect()     _ = client2.connect()           _ = client1.disconnect()           delegate2.expectation = XCTestExpectation(description: "Message received from echo service")     _ = client2.sendMessage(ofMessageType: eMTAction_Uninstall, withData: ["dummy": "data"])     wait(for: [delegate2.expectation!], timeout: timeout)   } This test sometimes succeeds and sometimes fails. Sometimes, the test expectation at the bottom is fulfilled, and sometimes the timeout is hit. I have tested with excessively long timeouts to rule-out processing-time as as factor. I am suspecting that calling invalidate() on one NSXPCConnection object is somehow causing a separate connection between the same client and service process to also be invalidated. Is it even a valid use-case to have multiple NSXPCConnection objects between a single XPC Service and XPC Client? When NSXPCConnection.invalidate() is called, does it inherently mean nothing can connect and communicate anymore, or is it just for that specific connection? When invalidate() is called, what does launchctl do to manage that service? Does it shut it down and allow subsequent connection attempts to spool the service up again? Does it prevent from any connections from ever being made again?
2
0
1.6k
Nov ’21