Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does NSDictionary's objectForKey: rely on identity or equality?

Say I have an object called Person which has the property socialSecurityNumber, and this class overrides the isEqual: method to return true when the social security number properties are equal. And say I've put a bunch of instances of Person into an NSDictionary.

If I now instantiate a newPerson object which happens to have the same social security number as one already in the dictionary, and I do [myDictionary objectForKey:newPerson], will it use the isEqual: and return YES, or will it compare pointers and return NO?

I know I can write a simple test to find out, but I want to understand how exactly objectForKey: finds a match in a dictionary, and generally how consistent this is across Cocoa (i.e. does NSArray's indexofObject: work the same?)

like image 516
lmirosevic Avatar asked Sep 13 '12 09:09

lmirosevic


2 Answers

NSDictionary works like a hashtable. So it uses both -hash and -isEqual: to find the object in the dictionary corresponding to the given key.

So to answer your question for NSDictionary, this uses isEqual: and not pointer comparison. But you also should implement hash in addition to isEqual: on your Person class for this to work.

  • From the NSDictionary Class Reference documentation:

A key-value pair within a dictionary is called an entry. Each entry consists of one object that represents the key and a second object that is that key’s value. Within a dictionary, the keys are unique. That is, no two keys in a single dictionary are equal (as determined by isEqual:).

  • From the isEqual: method documentation:

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.

  • This behavior is consistent across the various container classes in Cocoa. For example, from the NSArray's indexOfObject: method documentation:

Starting at index 0, each element of the array is sent an isEqual: message until a match is found or the end of the array is reached. This method passes the anObject parameter to each isEqual: message. Objects are considered equal if isEqual: (declared in the NSObject protocol) returns YES.


You should always read the documentation : as pointed out by the extracts quoted above, these kind of details are often explained in the "Discussion" or "Special Consideration" sections of the method documentation or in the "Overview" section of the class documentation itself.

like image 125
AliSoftware Avatar answered Nov 05 '22 02:11

AliSoftware


how consistent this is across Cocoa (i.e. does NSArray's indexofObject: work the same?)

It is consistent and at the same time it isn't. What I mean is that there are two methods that could be used: isEqual and hash. You should not be too much concerned about which is used when. What you should instead focus on is to respect the NSObject protocol requirements and make sure that if two objects are equal according to isEqual they also have the same hash.

From the isEqual documentation in the NSObject Protocol Reference

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.

like image 1
Analog File Avatar answered Nov 05 '22 02:11

Analog File