Objective-C: получение значения из NSMutableDictionary с пользовательским ключом объекта - PullRequest
4 голосов
/ 20 сентября 2011

Я всегда использовал NSDictionaries со строками в качестве ключей, и почти все примеры в Интернете / books / etc. подобные. Я решил, что попробую это с пользовательским объектом для ключа. Я ознакомился с реализацией метода copyWithZone и создал следующий базовый класс:

@interface CustomClass : NSObject
{
    NSString *constString;
}

@property (nonatomic, strong, readonly) NSString *constString;

- (id)copyWithZone:(NSZone *)zone; 

@end

@implementation CustomClass

@synthesize constString;

- (id)init
{
    self = [super init];
    if (self) {
        constString = @"THIS IS A STRING";
    }
    return self;
}

- (id)copyWithZone:(NSZone *)zone
{
    CustomClass *copy = [[[self class] allocWithZone: zone] init];
    return copy;
}

@end

Теперь я пытаюсь просто добавить один из этих объектов с простым строковым значением, а затем вернуть строковое значение для входа в консоль:

CustomClass *newObject = [[CustomClass alloc] init];
NSString *valueString = @"Test string";
NSMutableDictionary *dict =
[[NSMutableDictionary alloc] initWithObjectsAndKeys:valueString, newObject, nil];

    NSLog(@"Value in Dictionary: %@", [dict objectForKey: newObject]);
    // Should output "Value in Dictionary: Test string"

К сожалению, в журнале отображается (ноль). Я почти уверен, что упускаю что-то действительно очевидное и чувствую, что мне нужен еще один набор глаз.

Ответы [ 2 ]

7 голосов
/ 20 сентября 2011

NSDictionary ключевые объекты работают с тремя методами:

  • -(NSUInteger)hash
  • -(BOOL)isEqual:(id)other
  • -(id)copyWithZone:(NSZone*)zone

Реализация NSObject по умолчанию hash и isEqual: использует только указатель объекта, поэтому, когда ваш объект копируется с помощью copyWithZone:, копия и исходный объект больше не равны.

Чтовам нужно что-то вроде этого:

@implementation CustomClass

-(NSUInteger) hash;
{
    return [constString hash];
}

-(BOOL) isEqual:(id)other;
{
    if([other isKindOfClass:[CustomClass class]])
        return [constString isEqualToString:((CustomClass*)other)->constString];
    else
        return NO;
}
- (id)copyWithZone:(NSZone *)zone
{
    CustomClass *copy = [[[self class] allocWithZone: zone] init];
    copy->constString = constString; //might want to copy or retain here, just incase the string isn't a constant
    return copy;
}

@end

Это немного сложно выяснить из документации.Обзор для NSDictionary сообщает о isEqual: и NSCopying:

В словаре ключи уникальны.То есть, нет двух ключей в одном словаре (как определено isEqual :).В общем случае ключом может быть любой объект (при условии, что он соответствует протоколу NSCopying - см. Ниже), но обратите внимание, что при использовании кодирования значения ключа ключ должен быть строкой (см. «Основы кодирования значения ключа»).

И если вы посмотрите на документацию для -[NSObject isEqual:], она расскажет вам о hash:

Если два объекта равны,они должны иметь одинаковое хеш-значение.Этот последний пункт особенно важен, если вы определяете isEqual: в подклассе и намереваетесь поместить экземпляры этого подкласса в коллекцию.Убедитесь, что вы также определили хэш в своем подклассе.

0 голосов
/ 20 сентября 2011

Я думаю, что ваш класс должен определить:

- (BOOL)isEqual:(id)anObject

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

...