objective-cnsset

NSSet didn't contain the object even though they are equal


The Person class:

@interface Person : NSObject

@property (nonatomic, copy) NSString *name;

@end

I rewrite it's isEqual: method:

- (BOOL)isEqual:(id)object {
    Person *person = (Person *)object;
    return [self.name isEqualToString:person.name];
}

Then I did a test:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    Person *p1 = [[Person alloc] init];
    p1.name = @"Jack";

    Person *p2 = [[Person alloc] init];
    p2.name = @"Jack";

    if ([p1 isEqual:p2]) {
        NSLog(@"p1 isEqual p2");
    } else {
        NSLog(@"p1 not Equal p2");
    }

    NSMutableSet *set = [NSMutableSet set];
    [set addObject:p1];

    if ([set containsObject:p2]) {
        NSLog(@"contain p2");
    } else {
        NSLog(@"not contain p2");
    }
}

The console print:

p1 isEqual p2
not contain p2

About the method containsObject::

Each element of the set is checked for equality with anObject until a match is found or the end of the set is reached. Objects are considered equal if isEqual: returns YES.

So I'm a little confused now:

Now that p1 is equal to p2,why the set didn't contain p2


Solution

  • From the documentation for the NSObject protocol:

    If two objects are equal, they must have the same hash value. This last point is particularly important if you define isEqual: in a subclass and intend to put instances of that subclass into a collection. Make sure you also define hash in your subclass.