It seems it's happening only for Swift classes that extend NSObject
.
There’s a couple of options here:
-
If you’d like help getting to the bottom of this, you should open a DTS tech support incident. That’ll allow me to allocate time to look at your code in detail.
-
If you’d rather just treat this as a bug, that’s fine. In that case, please file your own bug about this [1], and post the bug number, just for the record. If you can attach a tiny test project to your bug report, that’d be grand.
ps The trick to creating tiny XPC test projects is to use loopback. I’ve pasted an example of this technique below. This technique is also super useful when testing your XPC code.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] Unfortunately the bug mentioned earlier in this thread (FB9605587) didn’t go anywhere.
import Foundation
@objc private protocol StringTransformer {
func uppercaseString(_ input: String, reply: @escaping (_ output: String) -> Void)
}
private final class Listener: NSObject, NSXPCListenerDelegate {
override init() {
let listener = NSXPCListener.anonymous()
self.listener = listener
self.endpoint = listener.endpoint
super.init()
listener.delegate = self
listener.resume()
print("server did start listening")
}
let listener: NSXPCListener
let endpoint: NSXPCListenerEndpoint
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection connection: NSXPCConnection) -> Bool {
print("server will accept connection")
_ = ServerConnection(connection: connection)
return true
}
}
private final class ServerConnection: NSObject, StringTransformer {
init(connection: NSXPCConnection) {
self.connection = connection
super.init()
connection.interruptionHandler = { print("server interrupted") }
connection.invalidationHandler = { print("server invalidated") }
connection.exportedInterface = NSXPCInterface(with: StringTransformer.self)
connection.exportedObject = self
connection.resume()
}
let connection: NSXPCConnection
fileprivate func uppercaseString(_ input: String, reply: @escaping (String) -> Void) {
print("server did receive request, input: \(input)")
let output = input.uppercased()
print("server will send response, output: \(output)")
reply(output)
}
}
private final class Client: NSObject {
init(connection: NSXPCConnection) {
self.connection = connection
super.init()
connection.remoteObjectInterface = NSXPCInterface(with: StringTransformer.self)
connection.interruptionHandler = { print("client interrupted") }
connection.invalidationHandler = { print("client invalidated") }
connection.resume()
}
let connection: NSXPCConnection
func sendRequest(_ input: String) {
print("--")
print("client will send request, request: \(input)")
let proxy = (self.connection.remoteObjectProxyWithErrorHandler { error in
print("client did not send request, proxy error: \(error)")
} as! StringTransformer)
proxy.uppercaseString(input) { output in
print("client did receive response, output: \(output)")
}
}
}
func main() {
let listener = Listener()
let client = Client(connection: NSXPCConnection(listenerEndpoint: listener.endpoint))
let timer = DispatchSource.makeTimerSource(queue: .main)
timer.setEventHandler {
client.sendRequest("Hello Cruel World! \(Date())")
}
timer.schedule(deadline: .now() + 1.0, repeating: 5.0)
timer.activate()
withExtendedLifetime(listener) {
withExtendedLifetime(client) {
dispatchMain()
}
}
}
main()