2009-04-08 31 views
36

我正在編寫一個上下文「工廠」,它將維護從某些Converter類繼承的轉換器/作用對象的字典。這個類有一個方法:在NSDictionary中使用類作爲關鍵字

- (Class)classResponsibility 

或者類似的東西,使得字符串轉換類將實施的方法:

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

然後到轉換器存儲在字典中,我已經在做一些希望像:

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

但是,編譯器抱怨說,類型「類」是用於的setValue的參數2無效的參數類型:forKey:方法。我曾經想避免將密鑰設置爲類的名稱(「NSString」),但如果這是最好的解決方案,那麼我將使用它。

回答

97

您使用的是setValue:forKey:,其僅以NSString爲關鍵字。您應該使用setObject:forKey:代替。類對象(指向類對象的指針可以作爲類型Class傳遞)是一個完整的Objective-C對象(類對象是其元類的一個實例,並且您可以在類對象上使用所有的NSObject方法;閱讀更多關於元類here),所以它們可以在任何使用對象的地方使用。

的字典鍵的另一個要求是,他們支持複製(即有copyWithZone:方法。做類對象支持此方法呢?其實,它的作用。NSObject類定義了一個類方法+copyWithZone:,其documentation明確。說,它「可以讓你使用一個類對象作爲重點,以一個NSDictionary對象」我認爲這是回答你的問題

+0

神奇的解釋! – 2012-08-08 20:10:42

+23

從XCode 4.5開始,你需要首先強制它不會得到警告:[dictionary setObject:object forKey:(id )someClass];看到這個答案http://stackoverflow.com/questions/12525324/unable-to-use-class-as-a-key-in-nsdictionary/12525479#12525479 – odyth 2012-09-24 02:35:55

4

-setValue:forKey:被記錄爲NSString作爲第二個參數。您必須使用NSStringFromClass()NSClassFromString()作爲適配器。

+0

你是正確的關於類是對象 – 2009-04-08 13:59:10

+0

請勿用於setValue方法的文檔:forKey:說使用鍵值編碼時,鍵只能是一個對象?否則,它不可能是任何實現NSCopying協議的對象,比如NSDictionary? – 2009-04-08 14:00:39

3

我正在尋找setObject:forKey:方法代替setValue:forKey :. setObject:forKey:的方法簽名接受(id)作爲兩種參數類型,並且更適合。

+0

@Graham Lee:類實現NSCopying。請參閱+ copyWithZone:方法的文檔:http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/doc/uid/20000050-copyWithZone_ – user102008 2011-07-29 23:12:45

+0

糟糕,我的錯誤。 – 2011-07-30 01:11:00

1

我剛做了一個類似的情況突然出現完全相同的錯誤消息:

[tempDictionary setObject:someDictionary forKey:someClass]; 

我所做的只是實現someClassNSCopying協議:

- (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或者直接在字典上枚舉。

[寫完這個之後,我看到你想要將類存儲爲密鑰。我要把它留在那裏,因爲如果我在搜索時發現了我的答案,我會節省很多時間。我沒有找到類似的東西。]

30

您的其他選擇是使用[NSValue valueWithNonretainedObject:yourObjectHere]從字符串以外的其他選項構造密鑰。我遇到了類似的問題,我想使用CoreData對象作爲鍵和其他值作爲值。這NSValue方法工作完美,我相信它的原意。要回到原始值,只需調用nonretainedObjectValue

3

儘管Class對象在NSDictionary中創建了一個非常好的鍵,但值得一提的是NSMapTable,它是在NSDictionary之後建模的,但爲什麼類型的對象適合提供更大的靈活性用作鍵和/或值,documented支持弱引用和任意指針。

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, 
}; 
相關問題