标签:oc
标签: objective-c
比较两个对象是否相等是一个常用的功能。==
操作符比较的不是对象,而是两个指针本身,一般来说这不是咱们所想要的。要想判断对象是否相等,应该使用 NSObject 协议中声明的isEqual:
方法来判断。一般来说,两个类型不同的对象总是不相等的。
如果你已经有过一些 OC 的编码经验的话,你一定自定义过isEqual:
方法。那么你是碰到过一些奇葩的问题呢?咱们先来看一段代码:
@interface Person : NSObject <NSCopying>
@property (nonatomic, copy) NSString *name;
@end
@implementation Person
- (BOOL)isEqual:(id)object {
if (self == object) return YES;
if (![object isKindOfClass:[Person class]]) return NO;
return [self.name isEqualToString:[object name]];
}
- (id)copyWithZone:(NSZone *)zone {
Person *person = [[Person allocWithZone:zone] init];
person.name = self.name;
return person;
}
@end
- (void)test {
Person *person = [[Person alloc] init];
person.name = @"Lili";
NSDictionary *dic = @{person: @1};
Person *personCopy = [person copy];
id object = [dic objectForKey:personCopy];
NSLog(@"%@", [person isEqual:personCopy] ? @"YES" : @"NO"); // 输出:YES
NSLog(@"%@", object); // 输出:(null)
}
这段代码定义了类:Person,实现了isEqual:
方法,并实现了NSCopying
协议。在测试中,以 Person 对象作为 key放到了字典中。再以 person 对象 copy 出一个新的对象:personCopy。但用这个 personCopy 作为 key 从字典中去取相应的值时,居然没有取到,输出为(null)。但咱们判断过 person 与 personCopy 对象呀:[person isEqual:personCopy]
,而且它是的确是相等的。
那么问题出在哪了?系统问题?不可能。咱们先看看NSDictionary中对key的要求:
在字典中,keys都是唯一的。也就是说,在一个字典中不会有两个key相等(通过
isEqual:
来判断)。一般来说,一个key可以是任何实现了NSCopying
协议的对象
NSCopying
协议只定义了copyWithZone:
方法,咱们也实现了,不是这个问题。若非问题出在isEqual:
上?这个方法声明在NSObject
协议中。来看看这个方法其中一段说明:
如果两个对象是相等的,那么它们就必须有相同的哈希码(hash value)。如果你的自定义类型定义了
isEqaul:
方法,并打算将其实例需要放到集合中,这点尤为重要。你应该确保在定义了isEqual:
方法的同时,也定义hash
方法。
也就是说,NSObject
协议中有两个用于判断等同性的方法:
- (BOOL)isEqual:(id)object;
- (NSUinteger)hash;
NSObject
类对这两个方法的默认实现是:当且仅当其“指针值”完全相等时,这两个对象才相等。若想在自定义类中正确实现这些方法,就必须先理解其约定。如果isEqual:
方法判定两个对象相等,那么其hash
方法也必须返回同一值。但是,如果两个对象的hash
方法返回同一个值,那么isEqual:
方法未必会认为两者相等。
哦,原来是这样呀,看来问题就是出在这里了。那么咱们写一个hash
方法出来看看:
// Person.m
- (NSUInteger)hash {
return [self.name hash];
}
// Test
- (void)test {
Person *person = [[Person alloc] init];
person.name = @"Lili";
NSDictionary *dic = @{person: @1};
Person *personCopy = [person copy];
id object = [dic objectForKey:personCopy];
NSLog(@"%@", [person isEqual:personCopy] ? @"YES" : @"NO"); // 输出:YES
NSLog(@"%@", object); // 输出:1
}
OK,这回没有问题了。
结论:实现isEqual:
方法的同时,要实现hash
方法!
标签:oc
原文地址:http://blog.csdn.net/womendeaiwoming/article/details/46419323