XPC没有正确注册类以进行收集

sud*_*-rf 8 xpc objective-c nsxpcconnection

我在10.8的一个应用程序中使用XPC.它具有为导出的接口和远程接口定义的协议的标准设置.我遇到的问题是在导出的界面上使用我的一个方法.

我有一个模型类,让我们调用它Foo.该类使用安全编码方法正确地符合NSSecureCoding,实现+supportsSecureCoding和编码/解码内部属性.通过我的导出接口上只涉及单个实例的方法传递此对象时,它可以正常工作.

当我想通过这些对象的集合,或将出现问题NSArrayFoo对象.以下是导出界面上签名的示例:

- (void)grabSomethingWithCompletion:(void (^)(NSArray *foos))completion;
Run Code Online (Sandbox Code Playgroud)

我已将该Foo课程列入白名单,如文档中所述:

NSSet *classes = [NSSet setWithObject:Foo.class];
[exportedInterface setClasses:classes forSelector:@selector(grabSomethingWithCompletion:) argumentIndex:0 ofReply:YES];
Run Code Online (Sandbox Code Playgroud)

现在这应该使得这个数组可以安全地复制到整个过程中并在另一侧进行解码.不幸的是,这似乎没有按预期工作.

在导出的协议上调用方法时,我收到一个异常:

警告:在解码收到的回复消息'grabSomethingWithCompletion:',丢弃传入消息和调用失败块时捕获到异常.

异常:解码调用参数1时发生异常:返回值:{v} void target:{@?} 0x0(块)参数1:{@} 0x0

例外:关键'NS.objects'的值是意外的类'Foo'.允许的类是'{(NSNumber,NSArray,NSDictionary,NSString,NSDate,NSData)}'.

这几乎看起来它甚至没有注册我之前执行的白名单.有什么想法吗?

DrG*_*arl 11

编辑2:这取决于您列入白名单的位置Foo.它需要在任何呼叫中列入白名单grabSomethingWithCompletion:.例如,如果您有一个实现和公开的服务:

- (void)takeThese:(NSArray *)bars reply:(void (^)(NSArray *foos))completion;

然后,您需要服务端Bar将传入连接列入白名单:

// Bar and whatever Bar contains.
NSSet *incomingClasses = [NSSet setWithObjects:[Bar class], [NSString class], nil];
NSXPCInterface *exposedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(InYourFaceInterface)];
[exposedInterface setClasses:incomingClasses forSelector:@selector(takeThese:reply:) argumentIndex:0 ofReply:NO];

// The next line doesn't do anything.
[exposedInterface setClasses:incomingClasses forSelector:@selector(takeThese:reply:) argumentIndex:0 ofReply:YES];
xpcConnection.exposedInterface = exposedInterface;
Run Code Online (Sandbox Code Playgroud)

第二部分必须在连接的另一端,无论与您的服务交谈如何:

NSSet *incomingClasses = [NSSet setWithObjects:[Foo class], [NSNumber class], nil];
NSXPCInterface *remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(InYourFaceInterface)];
[remoteObjectInterface setClasses:incomingClasses forSelector:@selector(takeThese:reply:) argumentIndex:0 ofReply:YES];
xpcConnection.remoteObjectInterface = remoteObjectInterface;
Run Code Online (Sandbox Code Playgroud)

总之,接收奇怪物体的任何东西都需要是将奇怪物体列入白名单的物体.不确定这是不是你的问题,但我相信这将是某个人的问题.

编辑:现在,我已经与XPC工作一段更长的时间,我知道我的答案,而解决一个问题,没有解决您的问题.我现在遇到了几次不同的时间,我仍然不确定如何在实现我自己的集合类之外解决它,这不太理想.

原答案:我知道你问这个问题已经有一段时间了,但经过大量的搜索后没有人回答这个问题,我想我会发布我的答案导致它的原因(可能有其他原因,但是这为我修好了).

在符合的类中NSSecureCoding,在该initWithCoder:方法中,您需要通过传入集合中包含的所有可能类的集合来显式解码集合.前两个是解码的标准示例,最后一个是解码集合:

if (self = [super init]) {
    self.bar = [aDecoder decodeInt64ForKey:@"bar"];
    self.baz = [aDecoder decodeObjectOfClass:[Baz class] forKey:@"baz"];
    NSSet *possibleClasses = [NSSet setWithObjects:[Collection class], [Foo class], nil];
    self.foo = [aDecoder decodeObjectOfClasses:possibleClasses forKey:@"foo"];
}
Run Code Online (Sandbox Code Playgroud)

因此,如果您的集合是包含NSStrings的集合,那么可能的类将是[NSSet class][NSString class].

我确定你已经从这个问题上解决了,但也许其他人需要这个答案和我一样多.