我们通常会通过Objective-C中Foundation库的NSDictionary与NSMutableDictionary来存放键值对。然而并不是所有Objective-C类都能作为NSDictionary的key来用的,这里将介绍如何将我们自己定义的Objective-C类可作为NSDictionary的键。
其实要满足这个条件也并不困难,NSDictionary的键要求该对象类型实现NSCopying这个协议。我们从Apple官方文档中很容易看到,NSCopying这个协议中就只有一个我们要实现的方法—— - (id)copyWithZone:(NSZone *)zone。其中,参数zone现在我们已经无需处理了,直接无视即可。
这个方法的实现可以有三种形式:
1、我们在这个方法里创建当前类的一个对象(使用alloc加init的形式),然后直接将该对象返回。
2、如果当前类继承了已经实现NSCopying协议的父类,那么我们直接可以返回调用父类的copyWithZone方法所返回的对象。
3、我们直接返回当前对象,做一次retain。
由于NSDictionary的键值查找会根据key对象的hash值,所以倘若我们在copyWithZone方法中新建一个,那么它与我们原本的对象就不一致了。所以在这种情景下我们要采用第三种实现方法,而这也是最简单的对copyWithZone的实现。
下面我们给出一个简单的示例:
@interface MyData : NSObject<NSCopying>
{
@public
int x, y;
}
@property (nonatomic, retain) NSString *str;
@end
@implementation MyData
@synthesize str;
- (void)dealloc
{
if(str != nil)
[str release];
[super dealloc];
}
- (id)copyWithZone:(NSZone *)zone
{
return [self retain];
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib
MyData *data1 = [[MyData alloc] init];
data1->x = 10;
data1->y = 20;
data1.str = @"hello";
MyData *data2 = [[MyData alloc] init];
data2->x = -10;
data2->y = -20;
data2.str = @"Bye";
NSDictionary<MyData*, NSString*> *dict = @{ data1:@"This", data2:@"That" };
[data1 release];
[data2 release];
NSLog(@"data1 string: %@", dict[data1]);
}
@end
我们可以发现,上述代码能正常工作。