Does NSSet's containsObject: test for pointer equality or value equality?

10,476

-containsObject: uses -isEqual: (and -hash) for equality testing. This applies to -removeObject: as well, and any other operations in NSSet that depend on some notion of equality.

Share:
10,476
Chris
Author by

Chris

iOS developer / contractor based in Sydney.

Updated on June 05, 2022

Comments

  • Chris
    Chris almost 2 years

    Say I have an NSSet with a string in it. If I send containsObject: with another string which is a different pointer but the exact same string value, will that return YES?

    Also, is it the same story when it comes to removeObject:? I.e., different objects with different pointers but the same string values will cause removal?

  • Jeff Laing
    Jeff Laing over 12 years
    Where is this documented? From what I can see, CFSet is clear that it uses POINTER equality by default, but I don't see NSSet clarifying what it uses?
  • jscs
    jscs over 12 years
    @user: The -[NSSet member:] documentation says that it uses isEqual:; member is one of the fundamental set methods, and it seems to be implied (though, you're right, not explicit) that containsObject: uses member.
  • Lily Ballard
    Lily Ballard over 12 years
    @user256413: All NSSet method that rely on equality must, by definition, use the same equality test. CFSet will use the pointer equality if you don't specify another equality function. If you use kCFTypeSetCallBacks then it uses CFEqual() as the equality comparison.
  • Chris
    Chris over 12 years
    Thanks, i was hoping that it used isEqual. Thanks for clearing that up
  • jowie
    jowie almost 10 years
    Can someone please explain this (apologies for the formatting): NSMutableString *str = [NSMutableString stringWithString:@"Hello"]; NSSet *set = [NSSet setWithObject:str]; NSLog(@"%d", [set containsObject:str]); // returns 1 [str appendString:@"BLA"]; NSLog(@"%d", [set containsObject:str]); // returns 0 NSLog(@"%d", [set.allObjects containsObject:str]); // returns 1
  • Lily Ballard
    Lily Ballard almost 10 years
    @jowie: NSSet is a hash table. -[NSMutableString hash] depends on the contents of the string. Mutating the string when it's in the set is explicitly unsupported (same as mutating it when it's in an NSDictionary), because that changes the hash, which makes lookup fail. However, set.allObjects produces an NSArray which does not use hash.
  • jowie
    jowie almost 10 years
    Interesting that it changes the hash. Why does it do that?
  • Lily Ballard
    Lily Ballard almost 10 years
    @jowie: Because the alternative is for every single NSMutableString to have the same hash, which would produce absolutely abysmal performance when stored in dictionaries/sets. The simple rule is you're not supposed to mutate an object that's been placed into an NSSet or used as the key for an NSDictionary.
  • jowie
    jowie almost 10 years
    So would it be a correct analogy to say that an NSSet is like a key-only NSDictionary (in the same way that an NSArray is a bit like a value-only NSDictionary)? Because NSSet items are unique, a bit like NSDictionary keys?
  • Lily Ballard
    Lily Ballard almost 10 years
    @jowie: An NSSet is effectively an NSDictionary that has no value, that's correct. But no, an NSArray is nothing like a value-only NSDictionary (besides all the performance differences, NSDictionarys are unsorted and NSArrays are sorted).