NSDictionary для исключения цикла - PullRequest
2 голосов
/ 22 августа 2011

У меня есть метод с этой частью кода:

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 объект d является NSCFString, но почему?

- ОБНОВЛЕНИЕ

Проблема в том, что когда 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"];
    }
}

Требуется улучшение.

Ответы [ 2 ]

3 голосов
/ 22 августа 2011

Я удивлен, что на самом деле все работает. Для словарей быстрое перечисление перечисляет клавиши . Вот почему он сообщает, что -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.

2 голосов
/ 22 августа 2011

Ошибка возникает из-за того, что в вашей переменной 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];
}
...