Ключи объекта с NSMutableDictionary (Objective-C) - PullRequest
7 голосов
/ 24 мая 2011

Я хочу сохранить несколько пар ключ-значение, причем ключом является мой собственный объект (ObjectA), который наследуется от NSObject, а значением является int.
Я пытаюсь использовать NSMutableDictionary. Я понимаю, что вы можете хранить только типы объектов в словаре, поэтому у меня есть следующее:

id value = [NSNumber numberWithInt:my_number];

[[self dictionary] setObject:value forKey:myObjectA];

Теперь это дает мне ошибку, говоря

- [ObjectA copyWithZone:]: нераспознанный селектор отправлен в экземпляр

это хорошо, я понимаю, что объектные ключи должны реализовывать протокол NSCopying. Однако потом я прочитал, что вы можете сделать это, обернув объекты с помощью NSValue.

Может кто-нибудь объяснить, как мне обернуть мои объекты, и как я могу найти значение по ключу? Я все еще могу использовать dictionary objectForKey:myObjectA или мне нужно обернуть myObjectA объектом NSValue во время поиска? Или я должен реализовывать NSCopying в моем собственном классе или вместо этого использовать строковый ключ?

Я ищу этот самый простой и легкий способ использования словаря, если мне придется реализовать строковый ключ и использовать вместо него setValue: forKey: но я бы лучше использовал ключ объекта, если смогу.

Ответы [ 4 ]

10 голосов
/ 24 мая 2011

Ключи словаря всегда копируются.Поэтому вам просто нужно реализовать протокол NSCopying для вашего класса, который является просто методом copyWithZone:.

Кроме того, вы должны реализовать метод isEqual: для своего класса.

Редактировать: Способ реализации copyWithZone: зависит от ряда факторов (основной фактор: глубокая или мелкая копия).См. Руководство Apple по реализации объекта и этот SO-ответ .

6 голосов
/ 24 мая 2011

Вы можете превратить id в NSValue с:

NSValue* value = [NSValue valueWithNonretainedObject:object];
...
id object_ = [value nonretainedObjectValue];

но вам нужно управлять владением за пределами словаря. Это будет беспорядок. Лучше принять NSCopying.


Существует также 4-й вариант: использовать CFDictionary, который позволяет объекту только CFRetain / CFReleased, но не копировать.

CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
     kCFAllocatorDefault, 0,
     &kCFTypeDictionaryKeyCallBacks,
     &kCFTypeDictionaryValueCallBacks
);

...

CFDictionarySetValue(dict, myObjectA, value);
...

CFRelease(dict);

А если вы программируете для Mac или iOS 6 и выше, попробуйте NSMapTable.

NSMapTable* dict = [[NSMapTable mapTableWithStrongToStrongObjects] retain];
...
[dict setObject:@"?" forKey:foo];
...
[dict release];
2 голосов
/ 22 октября 2013

В iOS 6 вы можете использовать NSMapTable (https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/NSMapTable_class/Reference/NSMapTable.html),, который позволяет вам выбирать слабые / сильные атрибуты для ключей и объектов.

0 голосов
/ 24 мая 2011

Вам не нужно оборачивать свой объект, используя NSValue. То, что у вас есть, будет работать, за исключением того, что вам не хватает части. Для класса myObjectA вам необходимо принять протокол NSCopying (что добавить, см. документы ). После добавления код, который вы разместили выше, должен работать правильно.

Возможно, вы захотите использовать строки вместо своего собственного объекта для ключа. Ключ должен быть строкой, если кодирование значения ключа будет использоваться для доступа к нему вообще. Поэтому использование строки облегчит жизнь, если вы сможете воспользоваться преимуществами кодирования значения ключа везде, где вы используете словарь.

...