Can't register a custom class in Swift 2 for XPC service

I'm trying to send a custom class through an XPC service in Swift 2. It works with a class written in Objective C, however with a Swift class, using the exact same code for class registration, I get a decode exception. Here's the class registration bit :


        let interface = NSXPCInterface(withProtocol: MyXPCProtocol.self)
        let currentExpectedClasses = interface.classesForSelector("myXPCMethod:", argumentIndex: 0, ofReply: false) as NSSet
        let allClasses = currentExpectedClasses.setByAddingObject(CustomClass.self)
        interface.setClasses(allClasses as Set<NSObject>, forSelector: "myXPCMethod:", argumentIndex: 0, ofReply: false)


and myXPCMethod :


    func myXPCMethod(message:CustomClass) {
        NSLog("ping back recevied with message :\(message)");
    }



with CustomClass being a Swift class, satisfying the NSSecureCoding protocol.


When trying to call myXPCMethod from the remote end, I get this error :


Exception caught during decoding of received message, dropping incoming message.

Exception: Exception while decoding argument 0 (#2 of invocation):

<NSInvocation: 0x63000006c4c0>

return value: {v} void

target: {@} 0x0

selector: {:} myXPCMethod:

argument 2: {@} 0x0

Exception: decodeObjectForKey: class "ImageDownloader.CustomClass" not loaded or does not exist


I guess the problem comes from the "ImageDownloader" prefix (that's the name of the XPC service sending the class) but I have no idea on how to solve it.


Any ideas ?


Thanks

Answered by LCS in 17487022

Have you tried using the @objc() attribute to set the name in the objective-C runtime?

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-XID_36


@objc(XYZTestClass) class TestClass
{
    / ... */
}


It should prevent the class from being tied to the different namespace of the Swift modules in the local and remote code.



Also, you might need your class to inherit from NSObject if it doesn't already, since NSXPCInterface wants a Set<NSObject> parameter and might use the NSObject base class methods.

Accepted Answer

Have you tried using the @objc() attribute to set the name in the objective-C runtime?

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-XID_36


@objc(XYZTestClass) class TestClass
{
    / ... */
}


It should prevent the class from being tied to the different namespace of the Swift modules in the local and remote code.



Also, you might need your class to inherit from NSObject if it doesn't already, since NSXPCInterface wants a Set<NSObject> parameter and might use the NSObject base class methods.

I tried the @objc attribute, but that didn't fix the problem.


EDIT : (back to this after being caught with something else) - I had added the '@objc' attribute but without specifying the name of the class, and indeed your reply is correct. Declaring my class as


@objc(CustomClass) class CustomClass: NSObject, NSSecureCoding

fixes the problem, even though it looks redundant.

Can't register a custom class in Swift 2 for XPC service
 
 
Q