Search code examples
objective-cnsset

How has Apple implemented NSSet?


Apple's docs currently DO NOT DOCUMENT NSSet's concept of "identity".

I have some bugs that appear to come from Apple's code. For instance, "[NSMutableSet minusSet]" never works for me as documented - but I'm pretty sure it's because of "identity".

e.g. from: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSSet_Class/Reference/Reference.html#//apple_ref/occ/cl/NSSet

containsObject:

Returns a Boolean value that indicates whether a given object is present in the set.

YES if anObject is present in the set, otherwise NO.

What does that MEAN?

FYI things I've tried:

  1. implemented "isEqual:" on all classes in the set
  2. checked that all classes are the same class (no subclass / superclass confusion)
  3. implementd NSCopying on all classes in the set (no effect)

Solution

  • In Cocoa, object equality is done by using isEqual: and hash:

    https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html

    From the notes for isEqual::

    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.

    Your subclasses will need to implement both of these, so that they return the same thing. Once they do this, then they can be used correctly in Cocoa Collections.

    The reason your NSSet equality wouldn't work, is because sets use hashes (it's stored as a hash table), hence if you only implemented isEqual:, then theres a chance (a good chance) that their hashes would be different.