在NSDictionary中使用class作为键

Cra*_*tis 37 dictionary objective-c

我正在编写一个上下文"工厂",它将维护一个继承自某些Converter类的转换器/动作对象的字典.这个类有一个方法:

- (Class)classResponsibility
Run Code Online (Sandbox Code Playgroud)

或类似的东西,这样StringConverter类将实现该方法:

- (Class)classResponsibility {
    return [NSString class];
}
Run Code Online (Sandbox Code Playgroud)

然后将该转换器存储在字典中,我曾希望做类似的事情:

[converters setValue:stringConverter forKey:[stringConverter classResponsibility]];
Run Code Online (Sandbox Code Playgroud)

但是编译器抱怨类型"Class"是setValue:forKey:方法的参数2的无效参数类型.我本来想避免将密钥设置为类的名称("NSString"),但如果这是最好的解决方案而不是我会使用它.

小智 98

你正在使用setValue:forKey:只需要NSStrings作为键.你应该使用setObject:forKey:而不是.类对象(类对象的指针可以作为类型传递Class)是一个成熟的Objective-C对象(类对象是其元类的一个实例,你可以NSObject在类对象上使用所有方法;阅读更多关于这里的元类,所以它们可以在任何使用对象的地方使用.

字典键的另一个要求是它们支持复制(即有copyWithZone:方法.类对象是否支持这种方法?事实上,确实如此.NSObject类定义了一个类方法 +copyWithZone:,其文档明确说明它"让你使用一个class对象作为NSDictionary对象的键".我认为这是你的问题的答案.

  • 从XCode 4.5开始,你需要先将它强制转换为不警告:[字典setObject:object forKey:(id <NSCopying>)someClass]; 看到这个答案http://stackoverflow.com/questions/12525324/unable-to-use-class-as-a-key-in-nsdictionary/12525479#12525479 (23认同)

小智 30

您的另一个选择是用于[NSValue valueWithNonretainedObject:yourObjectHere]从字符串以外的其他内容构造密钥.我遇到了类似的问题,我想使用CoreData对象作为键,其他东西作为值.这种NSValue方法很完美,我相信这是它的初衷.要回到原始值,只需致电nonretainedObjectValue


小智 5

虽然 Class 对象在 NSDictionary 中是一个完美的键,但值得一提的是 NSMapTable,它是在 NSDictionary 之后建模的,但在哪种类型的对象适合用作键和/或值方面提供了更大的灵活性,记录为支持弱引用和任意指针。