2013-05-27 2 views
7

Я использую XPC в одном из моих приложений на 10.8. У него стандартная настройка с протоколами, определенными для экспортируемого интерфейса и удаленного интерфейса. Проблема, с которой я сталкиваюсь, - это один из моих методов на экспортированном интерфейсе.XPC не правильно регистрирует классы для сбора

У меня есть класс модели, давайте просто назовите его Foo. Этот класс соответствует NSSecureCoding, реализует +supportsSecureCoding и правильно кодирует/декодирует внутренние свойства с использованием методов безопасного кодирования. При передаче этого объекта с помощью метода на моем экспортированном интерфейсе, который включает только один экземпляр, он отлично работает.

Проблема возникает, когда я хочу передать коллекцию этих объектов, или NSArray из 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

EDIT 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; 

Таким образом, независимо от того, что получение странных объектов должно быть одним из белых странных объектов. Не уверен, что это была твоя проблема, но я уверен, что это будет кто-то.

EDIT: Теперь, когда я работал с 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"]; 
} 

Так что, если вы коллекция представляет собой набор, содержащий NSStrings, возможные классы были бы [NSSet class] и [NSString class].

Я уверен, что вы перешли от этой проблемы, но, возможно, кому-то нужен этот ответ так же, как и я.

+0

Моя проблема была решена вашим первоначальным ответом. Хотя я использую XPC, проблема, с которой я столкнулась, была в реализации NSCoding. Я расшифровывал словарь и имел только белый список NSDictionary, но мне нужно было белить в список возможных типов значений внутри словаря, как показано в вашем примере. Благодарю. – Andrew

+0

@ Андрю - Да, я оставил все здесь, потому что все они проявляют свои проблемы очень похожими способами. Рад бы, по крайней мере, один из моих трех ответов мог помочь. – DrGodCarl

+0

«Оригинальный ответ» также решил эту проблему для меня.У меня был NSMutableArray строк на моем пользовательском объекте и использовал -decodeObjectOfClass: [NSMutableArray class] вместо использования -decodeObjectOfClasses: forKey: method. – Bryan

0

я столкнулся с этой же проблемой, я должен был явно Whitelist 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; 
Смежные вопросы