Comparing Objects in Objective C
Cocoa defines several methods for comparing objects in Cocoa:
- isEqual:
- isEqualToClassName
isEqual: compares the receiver to an object and will return NO if the object doesn’t belong to the same class as the receiver.
isEqualToClassName: compares the iVars of two objects of the same class.
Is nil equal to nil? Sending messages to nil
This is kind of a philosophical issue: if you consider nil to be the equivalent of an unknown value, then 2 unknown values are not necessarily the same. This seems to be the approach of the Cocoa designers.
I consider nil to be the object equivalent of zero, a null value. Therefore, two nil objects should be equal. And this is were you might get into trouble.
Any method sent to nil will get back the type equivalent of 0 (NO, 0, nil). This is a problem when sending isEqual to an object that happens to be nil. In this case you will always get NO, even if both objects are nil, and IMHO should be considered equal.
Overriding isEqual: and creating your own isEqualToClassName:
The recommended way to override, that solves the nil receiver issue is:
- check for pointer equality (gets rid of the nil receiver problem)
- check if parameter is nil or parameter is not of the same class
- otherwise, delegate to the corresponding isEqualTo
if you know both objects are of the same class and are not nil, ALWAYS use isEqualToClassName:
isEqual: & isEqualToClassName: code snippet
- (BOOL)isEqual:(id)other { if (other == self) return YES; if (!other || ![other isKindOfClass:[self class]]) return NO; return [self isEqualToWidget:other]; } - (BOOL)isEqualToWidget:(MyWidget *)aWidget { if (self == aWidget) return YES; if (![(id)[self name] isEqual:[aWidget name]]) return NO; if (![[self data] isEqualToData:[aWidget data]]) return NO; return YES; }