I have several processes maintaining NSXPConnection to an XPC service. The connections are bi-directional. Each side service and clients) of the connection exports an object, and an XPCInterface. The @protocols are different - to the service, and from the service to clients.
So long as all the "clients" fully implement their "call-back" @protocol, there's no problem. All works fine.
However - If a client does NOT implement a method in the "call back protocol", or completely neglects to export an object, or interface - and the service attempts to call back using the nonexistent method -- the XPC connection invalidates immediately.
So far - expected behaviour.
However, if I want the service to behave to the client a little like a "delegate" style -- and check first whether the client "respondsToSelector" or even - supports an interface BEFORE calling it, then this doesn't work.
When my XPC service tries the following on a client connection:
if (xpcConnection.remoteObjectInterface == nil)
os_log_error(myXPCLog, "client has no remote interface);
the condition is never met - i.e. the "remoteObjectInterface is never nil
even when the client does NOT configure its NSXPCConnection with any incoming NSXPCInterface, and does not set an "exportedObject"
Furthermore, the next check:
if ([proxy respondsToSelector:@selector(downloadFiltersForCustomer:withReply:)]) {
}
will not only fail - but will drop the connection. The client side gets the invalidation with the following error:
<NSXPCConnection: 0x600000b20000> connection to service with pid 2477 named com.proofpoint.ecd: received an undecodable message for proxy 1 (no exported object to receive message). Dropping message.
I guess the "undecidable message" is the respondsToSelector - because the code doesn't get to attempt anything else afterwards, the connection drops.
Is there a way to do this check "quietly", or suffering only "interruption", but without losing the connection,
However, if I want the service to behave to the client a little like a "delegate" style
Yeah, that’s not a pattern that’s well-supported by XPC.
I put this in the ‘XPC is not DO’ bucket [1]. The goal of DO was to hide the IPC as much as possible. That’s not a goal of XPC [2]. When you’re working with an XPC object you know you’re doing IPC and are expected to code accordingly. Thus, there’s no reason for forward -respondsToSelector:
and other low-level Objective-C runtime stuff.
You can try to make up for this yourself but my advice is that you not use this pattern.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] And thank goodness for that! (-:
[2] Ditto.