2015-12-29 2 views
0

Если есть NSMutableDictionary из Json данныхПроверьте ключ NSMutableDictionary равна нулю

NSMutableDictionary *returnedDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; 

Я знаю, что этот ключ returnedDict[@"data"][@"weather"][day][@"tides"] в некоторых случаях NSNull. Так что я получаю -[NSNull objectForKeyedSubscript:]

Итак, я пробую в соответствии с этим ответом How to check if an NSDictionary or NSMutableDictionary contains a key?, чтобы проверить, нет ли он или нет.

if (returnedDict[@"data"][@"weather"][day][@"tides"]){ some code } 

и

if (returnedDict[@"data"][@"weather"][day][@"tides"]!=[NSNull null]){ some code} 

не избежать, чтобы запустить {код}

Как проверить это в правильном направлении?

+0

ключ не имеет значения или значения? –

+0

В общем, разумно иметь все, что есть в if-clause, что-то, что оценивает настоящий BOOL. Использование побочных эффектов языка (в данном случае «любое ненулевое значение считается ДА») менее целесообразно, поскольку оно может вызвать непредвиденные ложные срабатывания (например, здесь, в вашем случае), это делает ваш код немного менее понятным для другие и ваше будущее. Кроме того, с Swift в мире сейчас разумно сделать это привычкой, так как в Swift требуется, чтобы любое if-clause оценивалось Bool. – Joride

+0

Значение представляет собой экземпляр NSNull –

ответ

2

Так что ваш вопрос:

Ваш сервер может вернуть null, чтобы указать, что объект нет. NSJSONSerialization преобразует это null в экземпляр NSNull. Теоретически это означает, что вместо result[a][b][c] вам нужно проверить, является ли result[a] словарем, и если да, то является ли result[a][b] словарем и т. Д. И т. Д., Который повторяется и подвержен ошибкам?

Возможно, самой простой вещью может быть удаление из словаря любой клавиши со значением NSNull, так что в следующий раз, когда вы попросите получить значение, вы получите обычный nil, который безопасен для сообщения на обычное соединение, правила обмена сообщениями?

NSJSONSerialization не будет делать это для вас, но это достаточно легко добавить после факта:

@interface NSDictionary(RemoveNullValues) 
- (NSDictionary *)ty_collectionWithoutNullValues; 
@end 

@interface NSArray(RemoveNullValues) 
- (NSArray *)ty_collectionWithoutNullValues; 
@end 

[...] 

@implementation NSDictionary(RemoveNullValues) 

- (NSDictionary *)ty_collectionWithoutNullValues { 

    NSMutableDictionary *reducedDictionary = [self mutableCopy]; 

    // remove any keys for which NSNull is the direct value 
    NSArray *keysEvaluatingToNull = [self allKeysForObject:[NSNull null]]; 
    [reducedDictionary removeObjectsForKeys:keysEvaluatingToNull]; 

    // ask any child dictionaries to do the same; note that it's safe 
    // to mutate reducedDictionary in this array because allKeys is a 
    // copy property; what you're iterating is not reducedDictionary 
    // but a snapshot of its keys when the array first began 
    for (id key in [reducedDictionary allKeys]) { 
     id child = reducedDictionary[key]; 
     if ([child respondsToSelector:@selector(ty_collectionWithoutNullValues)]) { 
      reducedDictionary[key] = [child ty_collectionWithoutNullValues]; 
     } 
    } 

    return [reducedDictionary copy]; 
} 

@end 

@implementation NSArray(RemoveNullValues) 
- (NSArray *)ty_collectionWithoutNullValues { 
    NSMutableArray *reducedArray = [NSMutableArray array]; 

    for (id child in self) { 
     if ([child isKindOfClass:[NSNull class]]) continue; 

     if ([child respondsToSelector:@selector(ty_collectionWithoutNullValues)]) { 
      [reducedArray addObject:[child ty_collectionWithoutNullValues]]; 
     } else { 
      [reducedArray addObject:child]; 
     } 
    } 

    return [reducedArray copy]; 
} 
@end 
+0

Это решение кажется лучшим, но пока я не могу заставить его работать в моем коде. –

+1

@WolfgangGiesel - Если у вас есть словари внутри массивов, в любой комбинации, что не редкость в JSON? Если это так, вам нужно пройти всю структуру JSON, чтобы искать словари, а затем применить этот ответ к тому, что вы найдете. – CRD

+0

Да, извинения, написанные неслучайно: предполагает словарь верхнего уровня с только детьми, которые являются словарями. Он действительно нуждается в расширении для обработки дела NSArray. Я попытаюсь отредактировать позже; обозначение как вики сообщества на данный момент, если кто-то еще захочет войти. – Tommy

0

использование if(![returnedDict[@"data"][@"weather"][day][@"tides"] isKindOfClass:[NSNull class]]) { some code }

+1

. Это будет работать только в том случае, если последним значением является 'NSNull', если какой-либо из них является' NSNull', то приложение будет аварийно завершено. – Cristik

0

Вы должны прочитать этот ответ в связи с принятым ответом и комментарием к вопросу Is there NSMutableDictionary literal syntax to remove an element?

В ответ на связанный ответ вы можете спокойно удалить все NSNull и вернуть nil вместо этого, если вы получите доступ к элементу с использованием синтаксиса literal (т.е. не с помощью objectForKey:), добавив следующее приложение:

@implementation NSDictionary (ClobberNSNull) 

- (id) objectForKeyedSubscript:(id<NSCopying>)key 
{ 
    id result = [self objectForKey:key]; 
    return result == NSNull.null ? nil : result; 
} 

@end 

Теперь, когда вы используете синтаксис:

dictionary[key] 

, если соответствующий объект является NSNull то nil будет возвращен только в случае, если ключа не было.

Есть оговорки, см. Связанный вопрос, и вам нужно решить, подходит ли этот подход для вашей ситуации. Но это просто.

НТН

Примечание: Перед тем как кто-то комментарии, NSNull одноэлементно так == ОК.

+0

Итак, кажется, что (а) работает (б) решает проблему (с) следует шаблон Apple и (d) содержит * caveat *, и он получает молчаливое голосование? Суровая. – CRD

+0

Отказ от ответственности: отрицательный голос не от меня. Это было сказано: может быть, предостережение, что это повлияет на все словари? – Tommy

+0

@Tommy - Ну, это оговорка (хотя, вероятно, и не значительная), и, возможно, вы правы, это то, что оскорблено. Кто знает? – CRD

Смежные вопросы