前言
根据“等同性”来比较对象是一个非常有用的功能。不过,按照 == 操作符比较出来的结果未必是我们想要的,因为该操作比较的是两个指针本身,而不是其所指的对象。应该使用NSOject协议中声明的“isEqual”:方法来判断两个对象的等同性。一般来说,两个类型不同的对象总是不相等的。下面的例子:
NSString *test1 = @"test";
NSString *test2 = [NSString stringWithFormat:@"%@",@"test"];
BOOL boolA = (test1 == test2); // NO
BOOL boolB = [test1 isEqual:test1]; // YES
BOOL boolC = [test1 isEqualToString:test2]; // YES
从例子中可看到 == 与等同性判断方法的差别,NSString自己实现一个等同性判断方法,名叫“isEqualToString:”。
NSOject协议中有两个用于判断等同性的关键方法:
// 判断两个对象是否相等(可以自定义规则)
- (BOOL)isEqual:(id)object ;
- (NSUInteger)hash ;
NSOject类对这两个方法的默认实现是:当且仅当其内存地址完全相等时对象才相等。我们可以通过覆写上面的方法,自定义判断连个对象是否相等。
比如下面这个类
@interface Person : NSObject
@property (nonatomic,copy) NSString*firstName;
@property (nonatomic,copy) NSString*lastName;
@property (nonatomic,assign) NSUInteger age;
@end
如果我比较的规则是:Person的所有字段都相等,那么这两个对象就相等。
- (BOOL)isEqual:(id)object {
if (self == object) {
return YES;
}
if ([self class] != [object class]) {
return NO;
}
Person *p = (Person*)object;
if (![_firstName isEqualToString:p.firstName]) {
return NO;
}
if (![_lastName isEqualToString:p.lastName]) {
return NO;
}
if (_age!=p.age) {
return NO;
}
return YES;
}
- (NSUInteger)hash {
// 第一种 return 3122;
// 第二种
// NSString *stringToHash = [NSString stringWithFormat:@"%@:%@:%i",_firstName,_lastName,_age];
//
// return [stringToHash hash];
// 第三种(推荐,相比第二种方式,第三种不需要再创建一个字符串,性能肯定比第二种快)
NSUInteger fistNameHash = [_firstName hash];
NSUInteger lastNameHash = [_lastName hash];
NSUInteger ageHash = _age;
return fistNameHash^lastNameHash^ageHash;
}
另外我们还可以根据自己需求定制不能规则来判断两个对象是否相同。