2013-10-25 2 views
4

У меня есть некоторые проблемы с NSMutableSet в Objective-C. Я узнал, что NSSet будет сравнивать хэш-код двух объектов, чтобы решить, идентичны они или нет. Проблема заключается в том, что я реализовал класс, который является подклассом NSObject. В этом классе есть свойство NSString *name. То, что я хочу сделать, - это когда экземпляры этого пользовательского класса имеют одинаковое значение переменной «имя», они должны быть идентичными, и такой идентичный класс не должен дублироваться при добавлении в NSMutableSet.Дублированный пользовательский объект в NSSet

Поэтому я переопределяю функцию - (NSUInteger)hash, и отладка показывает, что она возвращает тот же хеш для моих двух экземпляров obj1, obj2 (obj1.name == obj2.name). Но когда я добавил obj1, obj2 в NSMutableSet, NSMutableSet все еще содержал оба obj1, obj2 в нем.

Я пробовал два NSString, которые имеют такое же значение, а затем добавили их в NSMutableSet, набор будет только один NSString.

Что может быть решением? Спасибо за любую помощь!

Обычай Класс: Object.h:

#import <Foundation/Foundation.h> 

@interface Object : NSObject 

@property (retain) NSString *name; 

@end 

Object.m

@implementation Object 
@synthesize name; 

-(BOOL)isEqualTo:(id)obj { 
    return [self.name isEqualToString:[(Object *)obj name]] ? true : false; 
} 

- (NSUInteger)hash { 
    return [[self name] hash]; 

} 
@end 

и главный:

#import <Foundation/Foundation.h> 
#import "Object.h" 

int main(int argc, const char * argv[]) 
{ 
    @autoreleasepool { 
     Object *obj1 = [[Object alloc]init]; 
     Object *obj2 = [[Object alloc]init]; 
     obj1.name = @"test"; 
     obj2.name = @"test"; 
     NSMutableSet *set = [[NSMutableSet alloc] initWithObjects:obj1, obj2, nil]; 
     NSLog(@"%d", [obj1 isEqualTo:obj2]); 
     NSLog(@"%ld", [set count]); 
    } 
    return 0; 
} 
+2

Вы также переопределить 'IsEqual:'? – Sebastian

+3

Можете ли вы показать свою реализацию 'hash',' isEqual' и как вы добавляете объекты в набор? – Sebastian

+2

Вы внедрили неправильный метод. 'isEqual:' не то же самое, что 'isEqualTo:' Вы также не можете предположить, что объект, который вы тестируете для равенства, даже _has_ имеет свойство, называемое 'name'. Вы должны прочитать [сообщение Майка Эша о равенстве и хэшировании] (http://www.mikeash.com/pyblog/friday-qa-2010-06-18-implementing-equality-and-hashing.html). –

ответ

6

Вместо реализации isEqualTo: вы должны реализовать isEqual:

- (BOOL)isEqual:(id)object { 
    return [object isKindOfClass:[MyObject class]] && 
      [self.name isEqual:[(MyObject *)object name]]; 
} 

Это (вероятно, ошибочно) возвращают NO если оба self.name и object.name являются nil. Если вы хотите вернуть YES, если оба свойства nil вы должны использовать

- (BOOL)isEqual:(id)object { 
    if ([object isKindOfClass:[MyObject class]]) { 
     return (!self.name && ![(MyObject *)object name]) || 
     [self.name isEqual:[(MyObject *)object name]]; 
    } 
    return NO; 
} 
+0

!!! Большое спасибо. Слишком глупо ... – john

+0

Использование '[self class]' может привести к '[a isEqual: b]! = [B isEqual: a]', который, как мне кажется, никогда не будет желательным (когда 'b' является подклассом' a' без переопределения 'isEqual:'). – Sebastian

+1

В частности, если 'a' является экземпляром подкласса класса' b', '[a isEqual: b]' будет возвращать NO (поскольку 'b' не является классом' a') и '[b isEqual: a]' вернет YES, потому что 'a' является своего рода классом' b'. (при использовании '[self class]') – Sebastian

 Смежные вопросы

  • Нет связанных вопросов^_^