30

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?

jscs
  • 63,694
  • 13
  • 151
  • 195
Chris
  • 39,719
  • 45
  • 189
  • 235
  • 3
    Did you try it? Do you have any reason to believe that it wouldn't? – jscs Dec 07 '11 at 05:04
  • 1
    If it considered that two strings with the same content were the same object, you could not get the second string into the set so the removeObject: part of the question is moot. NSSet claims to provide "static sets of distinct objects" - not "static sets of non-equal objects". – Jeff Laing Dec 07 '11 at 05:35
  • Yes this works. Can confirm containsObject tests for equal strings. I used it to optimize core data updates so I don't have to look up an entity every time to see if it exists. I just use my key field which is a string. – SpaceTrucker Aug 15 '16 at 18:05

1 Answers1

40

-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.

Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
  • 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? – Jeff Laing Dec 07 '11 at 05:34
  • 2
    @user: The [`-[NSSet member:]`](http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSSet_Class/Reference/Reference.html#//apple_ref/doc/uid/20000143-CHDCHEDC) documentation says that it uses `isEqual:`; `member` is one of [the fundamental set methods](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Collections/Articles/Sets.html%23//apple_ref/doc/uid/20000136-SW3), and it seems to be implied (though, you're right, not explicit) that `containsObject:` uses `member`. – jscs Dec 07 '11 at 05:43
  • 4
    @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. – Lily Ballard Dec 07 '11 at 07:58
  • Thanks, i was hoping that it used isEqual. Thanks for clearing that up – Chris Dec 07 '11 at 23:15
  • 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` – jowie Apr 24 '14 at 09:25
  • 2
    @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`. – Lily Ballard Apr 25 '14 at 03:51
  • Interesting that it changes the hash. Why does it do that? – jowie Apr 25 '14 at 08:34
  • 2
    @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`. – Lily Ballard Apr 26 '14 at 07:31
  • 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? – jowie Apr 29 '14 at 07:34
  • 1
    @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, `NSDictionary`s are unsorted and `NSArray`s are sorted). – Lily Ballard Apr 30 '14 at 02:08