在NSDictionary中使用class作为键

时间:2009-04-08 13:42:10

标签: objective-c dictionary

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

- (Class)classResponsibility

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

- (Class)classResponsibility {
    return [NSString class];
}

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

[converters setValue:stringConverter forKey:[stringConverter classResponsibility]];

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

7 个答案:

答案 0 :(得分:98)

您正在使用仅setValue:forKey:作为键的NSString。你应该使用setObject:forKey:代替。类对象(指向类对象的指针可以作为类型Class传递)是一个成熟的Objective-C对象(类对象是其元类的一个实例,你可以使用所有{{1类对象上的方法;阅读有关元类here)的更多信息,因此可以在任何使用对象的地方使用它们。

字典键的另一个要求是它们支持复制(即使用NSObject方法。类对象是否支持此方法?事实上,它确实如此.NSObject类定义了一个类方法< / em> copyWithZone:,其documentation明确表示它“允许您使用类对象作为NSDictionary对象的键”。我认为这是您问题的答案。

答案 1 :(得分:30)

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

即可

答案 2 :(得分:4)

记录

-setValue:forKey:NSString作为第二个参数。您必须使用NSStringFromClass()NSClassFromString()作为适配器。

答案 3 :(得分:3)

我正在寻找 setObject:forKey :方法而不是setValue:forKey:。 setObject:forKey的方法签名:接受(id)作为两种参数类型,并且更适合。

答案 4 :(得分:3)

虽然Class对象在NSDictionary中是一个非常好的键,但值得一提的是NSMapTable,它是以NSDictionary为模型的,但它提供了更多的灵活性,可以使哪种对象适合用作键和/或值,{{ 3}}支持弱引用和任意指针。

答案 5 :(得分:1)

我刚刚遇到了类似的情况,并出现了完全相同的错误消息:

[tempDictionary setObject:someDictionary forKey:someClass];

我所做的就是在NSCopying中实施someClass协议:

- (id)copyWithZone:(NSZone *)zone
{
    id copy = [[[self class] allocWithZone:zone] init];
    [copy setId:[self id]];
    [copy setTitle:[self title]];
    return copy;
}

我认为发生的事情是someClass的副本正在被用作关键,但由于我的对象不知道如何复制自己(源自NSObject copyWithZone

我用我的方法发现的一件事是它使用一个对象作为关键。除非我已经实例化了对象,否则我会不断调用allKeys或者只是枚举字典。

[写完之后,我发现你想把这个类存储为密钥等。我把它留在那里是因为如果我在搜索时找到答案,我会节省很多时间。我当时没有找到这样的东西。]

答案 6 :(得分:0)

您可以将这些类用作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,
};