2011-08-22 80 views
2

我已經與這部分代碼的方法:的NSDictionary for循環異常

NSDictionary *tmpDict = [self getJsonDictionary]; 

NSInteger tmpID; 

for (NSDictionary *d in tmpDict) { 
    tmpID = [[d objectForKey:@"id"] integerValue]; 
} 

tmpDict是具有可變大小的NSDictionary。如果tmpDict含有至少2個對象(2 NSDictionary中)它工作得很好,但如果只包含1個對象(1 NSDictionary中)拋出此異常:

-[NSCFString objectForKey:]: unrecognized selector sent to instance 0x4e866d0 
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString objectForKey:]: unrecognized selector sent to instance 0x4e866d0' 

爲什麼呢?如何修復如果tmpDict只有1個對象?

可能for (NSDictionary *d in tmpDict)是問題,當tmpDict有1個對象dNSCFString,但是爲什麼?

- UPDATE

問題是,當tmpDict有1個項目(一個的NSDictionary)的for (NSDictionary *d in tmpDict)採取各種鍵/值項的字典,這是異常的原因。否則,如果tmpDict有2+項是NSDictionary的NSDictionary,它運作良好。我需要一種方法來解決這個問題,仍然使用for循環。想法?

- 更新2 *

其實這段代碼的作品,但它是多餘的:

if ([tmpObject isKindOfClass:[NSDictionary class]]) { 
    tmpID = [[tmpObject objectForKey:@"id"] integerValue]; 
    tmpProp2 = [tmpObject objectForKey:@"prop2"]; 
    tmpProp3 = [tmpObject objectForKey:@"prop3"]; 
    tmpProp4 = [tmpObject objectForKey:@"prop4"]; 
} else if ([tmpObject isKindOfClass:[NSArray class]]) { 
    for (NSDictionary *d in tmpObject) { 
     tmpID = [[d objectForKey:@"id"] integerValue]; 
     tmpProp2 = [d objectForKey:@"prop2"]; 
     tmpProp3 = [d objectForKey:@"prop3"]; 
     tmpProp4 = [d objectForKey:@"prop4"]; 
    } 
} 

它需要改進。

+0

WRT更新2:唯一的改進是你可以從字典中獲取項目。否則,這看起來不錯。 –

回答

3

我很驚訝,它在所有工作實際。對於字典,快速列舉枚舉。這就是爲什麼它告訴你-objectForKey:已發送到NSCFString,因爲來自JSON的字典的密鑰始終是一個字符串。

你應該,也許,這樣做:

for (id d in [tmpDict objectEnumerator]) 
{ 
    // Objects in a JSON dictionary aren't necessarily dictionaries 
    if([d isKindOfClass:[NSDictionary class]]) 
    { 
     tmpID = [[d objectForKey:@"id"] integerValue]; 
    } 
} 

一個可能的原因可能有兩個庫的工作是,如果頂級項目實際上是一個數組,而不是一本字典。如果您有:

[ { "id" : 1 }, { "id" : 2 } ] 

您的JSON解析器會給你一個NSArray,而不是一個NSDictionary,它可以與你的代碼,即使你認爲你的頂級項目是一個字典解析。

編輯:看到您的更新,我相信這是發生了什麼。如果你有一個對象,你的JSON字符串看起來像:

{ "id" : 1, "prop2" : "value1", "prop3" : "value1", "prop4" : "value1" } 

如果你有兩個對象,它可能是這樣的:

[ 
     { "id" : 1, "prop2" : "value1", "prop3" : "value1", "prop4" : "value1" }, 
     { "id" : 2, "prop2" : "value1", "prop3" : "value1", "prop4" : "value1" } 
] 

聲明的方括號,這意味着JSON陣列。

+0

謝謝你的回覆,你能解釋一下爲什麼你使用'objectEnumerator'?檢查我的新更新 –

+0

@Fred:因爲objectEnumerator返回的是對象而不是鍵 – JeremyP

+0

@Fred:你的最新更新與我在我的答案的第二部分中的推測是一致的。如果你有一本字典,那麼你的JSON就是一本字典,如果你有超過o ne字典你的JSON是字典的一個數組。 – JeremyP

2

由於在tmpDict變量中存在NSString類型的對象,因此可以使用此錯誤。

for (id *d in tmpDict) 
{ 
    if([d isKindOfClass:[NSDictionary class]]) 
     tmpID = [[d objectForKey:@"id"] integerValue]; 
    else 
     tmpID = [(NSString *)d intValue]; 
} 

,而不是這個

for (NSDictionary *d in tmpDict) { 
    tmpID = [[d objectForKey:@"id"] integerValue]; 
} 
+0

沒關係,但我需要'tmpID = [[tmpDict objectForKey @「id」] integerValue]'如果d不是NSDictionary(如果tmpDict只有1個項目,我仍然需要取對象,但我應該使用'[tmpDict objectForkey ]' –

+0

這可以工作,但如果在NSDictionary中有多個鍵/值對,則else塊重複。 –

+0

您可以在for循環的末尾檢查是否更新tmpID值,如果是的,那麼不要改變它的值 – Robin