In doing some work, I realized I didn't understand XPC (or at least, the higher-level APIs) at all. So I did what I usually try to do, which is to write a completely, brain-dead simple program to use it, and then keep expanding until I understand it. This also, to my utmost embarrassment, will make it transparently clear how ignorant I am. (Note that, for this, I am not using Xcode -- just using swiftc
to compile, and then manually run.)
I started with this, to be the server side:
import Foundation
class ConnectionHandler: NSObject, NSXPCListenerDelegate {
override init() {
super.init()
print("ConnectionHandler.init()")
}
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
print("ConnectionHandler.listener()")
return false
}
}
let handler = ConnectionHandler()
let listener = NSXPCListener(machServiceName: "com.kithrup.test")
listener.delegate = handler
listener.resume()
print("listener = \(listener)")
dispatchMain()
That ... does absolutely nothing, of course, but runs, and then I tried to write the client side:
import Foundation
@objc protocol Hello {
func hello()
}
class HelloClass: NSObject, Hello {
override init() {
super.init()
}
func hello() {
print("In HelloClass.hello()")
}
}
let hello = HelloClass()
let connection = NSXPCConnection(machServiceName: "com.kithrup.test", options: [])
connection.exportedInterface = NSXPCInterface(with: Hello.self)
let proxy = connection.remoteObjectProxyWithErrorHandler({ error in
print("Got error \(error)")
}) as? Hello
print("proxy = \(proxy)")
connection.resume()
dispatchMain()
That gets proxy
as nil
. Because it can't coerce it to something of Hello
protocol. And at no point, do I get the message from the server-side listener.
So clearly I am doing everything wrong. Can anyone offer some hints?
What happens if you remove 'as? Hello'. I never practiced, so I am more ignorant than you probably. I found this interesting link: h t t p s : / / matthewminer. com/2018/08/25/creating-an-xpc-service-in-swift.html What they do differently is to define connection.exportedInterface in the listener.
If I remove 'as? Hello', it gives me a value, but then I can't call the method on it. Note that I have
connection.exportedInterface = NSXPCInterface(with: Hello.self)
in there.