在NSDictionary中使用类作为键
我正在编写一个上下文“工厂”,将维护从某些Converter类inheritance的转换器/代理对象的字典。 这个类有一个方法:
- (Class)classResponsibility
或类似的东西,这样一个StringConverter类将实现该方法为:
- (Class)classResponsibility { return [NSString class]; }
然后把这个转换器存储在字典中,我希望能做到这样的事情:
[converters setValue:stringConverter forKey:[stringConverter classResponsibility]];
但是,编译器会抱怨,对于setValue:forKey:方法的参数2,“Class”types是无效的参数types。 我曾经希望避免将密钥设置为类的名称(“NSString”),但是如果这是最好的解决scheme,那么我将使用它。
你正在使用setValue:forKey:
它只以NSString
s为关键字。 你应该使用setObject:forKey:
来代替。 一个类对象(指向类对象的指针可以作为类的Class
来传递)是一个完整的Objective-C对象(一个类对象是它的元类的一个实例,你可以在一个类对象上使用所有的NSObject
方法; 在这里阅读更多关于元类的内容),所以它们可以在任何使用对象的地方使用。
字典的另一个关键要求是它们支持复制(即有copyWithZone:
方法。类对象是否支持这个方法?事实上,它的确如此。NSObject类定义了一个类方法 +copyWithZone:
的文档明确地说明了它“让你使用一个类对象作为一个NSDictionary对象的关键”。我想这就是你的问题的答案。
你的另一个select是使用[NSValue valueWithNonretainedObject:yourObjectHere]
来构造除了string以外的其他键。 我遇到了类似的问题,我想用一个CoreData对象作为键和其他值作为值。 这个NSValue
方法工作完美,我相信这是它的原意。 要回到原始值,只需调用nonretainedObjectValue
-setValue:forKey:
logging为将NSString
作为第二个参数。 你将不得不使用NSStringFromClass()
和NSClassFromString()
作为适配器。
我正在寻找setObject:forKey :方法,而不是setValue:forKey :. setObject:forKey:的方法签名接受(id)作为两个参数types,并且更适合。
虽然一个Class对象在NSDictionary中是一个非常好的键,但值得一提的是NSMapTable,它是在NSDictionary之后build模的,但是提供了更多的灵活性,以便哪些对象适合用作键和/或值, logging为支持弱引用和任意指针。
我刚刚有一个类似的情况,出现了完全相同的错误信息:
[tempDictionary setObject:someDictionary forKey:someClass];
我所做的只是在someClass
实现someClass
协议:
- (id)copyWithZone:(NSZone *)zone { id copy = [[[self class] allocWithZone:zone] init]; [copy setId:[self id]]; [copy setTitle:[self title]]; return copy; }
我认为发生的事情是为了用作关键字而创build了一个someClass
的副本,但是由于我的对象不知道如何复制自身(从NSObject
派生,它没有超类中的copyWithZone
)它迟疑了。
我用我的方法发现的一件事是它使用一个对象作为关键。 除非我已经实例化对象,否则我会不断地调用allKeys
或者直接在字典上枚举。
[写完这个之后,我看到你想把class级存储成密钥。 我要把它留在那里,因为如果我在search时发现了我的答案,我会节省很多时间。 那么我没有发现这样的事情。]
你可以像NSDictionary
的键一样使用类:
@{ (id)[MyClass1 class] : @1, (id)[MyClass2 class] : @2, (id)[MyClass3 class] : @3, (id)[MyClass4 class] : @4, };
甚至像这样:
@{ MyClass1.self : @1, MyClass2.self : @2, MyClass3.self : @3, MyClass4.self : @4, };