2013-05-27 20 views
7

我在10.8的一個應用程序中使用XPC。它具有爲導出界面和遠程界面定義的協議的標準設置。我遇到的問題是在導出的界面上使用我的一種方法。XPC沒有正確註冊類的集合

我有一個模型類,讓我們只是叫它Foo。該類符合NSSecureCoding,實現+supportsSecureCoding,並使用安全編碼方法正確編碼/解碼內部屬性。當通過只包含單個實例的導出接口上的方法傳遞此對象時,它可以正常工作。

當我想要傳遞這些對象的集合或的Foo對象時,會發生此問題。這是一個什麼樣的輸出接口上的簽名看起來像一個例子:

- (void)grabSomethingWithCompletion:(void (^)(NSArray *foos))completion; 

而且我已經列入白名單Foo類,如文檔中指出:

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

現在,這應該讓這個這個數組可以在整個過程中安全地複製並在另一側解碼。不幸的是,這似乎沒有按預期工作。

當調用上導出的協議的方法中,我收到異常:

警告:異常到消息 接收的回覆的解碼期間捕獲「grabSomethingWithCompletion:」,丟棄傳入消息和 呼叫失敗塊。

異常:異常而解碼調用的參數1: 返回值:{V}空隙目標:{@?}爲0x0 (塊)參數1:{@}爲0x0

例外:密鑰值' NS.objects'是意想不到的類 'Foo'。允許的類是'{( NSNumber, NSArray, NSDictionary, NSString, NSDate, NSData)}'。

這幾乎看起來它甚至沒有註冊我之前執行的白名單。有什麼想法嗎?

+0

看起來好像也需要做'NSPropertyListSerialization'。它也似乎[你並不孤單](https://gist.github.com/AlanQuatermain/3209230) – CodaFi

回答

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; 

這第二部分具有去連接的另一端,無論是與你的服務對話:

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; 

總之,無論是接收奇怪的物體需要成爲將這些奇怪物體列入白名單的人。不知道這是否是你的問題,但我相信它會是某人的。

編輯:現在,我一直在與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"]; 
} 

所以,如果你收集含有NSString的一集,可能的類是[NSSet class][NSString class]

我相信你已經從這個問題上移開了,但也許有人需要這個答案和我一樣。

+0

我的問題已被您的原始答案解決。當我使用XPC時,我遇到的白名單問題是在NSCoding實現中。我正在解碼字典,只有NSDictionary列入白名單,但我需要將字典中可能的值類型列入白名單,就像您在示例中顯示的一樣。謝謝。 – Andrew

+0

@Andrew - 是的,我把所有東西都留在了這裏,因爲它們都以非常相似的方式表現出他們的問題。很高興我的三個答案中的至少一個可以提供幫助。 – DrGodCarl

+0

「原始答案」也爲我解決了這個問題。我在自定義對象上有一個NSMutableArray字符串,並使用-decodeObjectOfClass:[NSMutableArray類]而不是使用-decodeObjectOfClasses:forKey:方法。 – Bryan

0

我遇到過同樣的問題,我必須明確白名單NSArray*以及

NSSet *classes = [NSSet setWithObjects: [Foo class], [NSArray class], nil]; 

這是一個有點違反直覺,因爲documentation沒有提到這一要求。

0

其實看來你需要你的自定義類添加到白名單中已有的:

NSSet currentClasses = [remoteObjectInterface classesForSelector:@selector(takeThese:reply:) argumentIndex:0 ofReply:YES]; 


NSSet *allIncomingClasses = [currentClasses setByAddingObjectsFromSet:[NSSet setWithObjects:[Foo class], [NSNumber class], nil]; 

NSXPCInterface *remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(InYourFaceInterface)]; 
[remoteObjectInterface setClasses:allIncomingClasses forSelector:@selector(takeThese:reply:) argumentIndex:0 ofReply:YES]; 
xpcConnection.remoteObjectInterface = remoteObjectInterface;