NSDictionaray dictionaryWithObjectsAndKeys добавление значения NULL
Я хочу создать NSDictionary с + [NSDictionary dictionaryWithObjectsAndKeys:]. У одного из моих ключей есть строка, но иногда она может быть nil
, Если строка nil
любые другие пары ключей значений, которые я добавлю позже, будут игнорироваться, потому что список преждевременно завершен. Каков стандартный способ справиться с возможностью того, что nil
в NSDictionary
?
3 ответа
Вы должны проверить, является ли строка нулевой. Если это так, добавьте [NSNull null]
вместо вашей строки.
Создание объектов NSDictionary может быть затруднительным, если у вас много объектов, и если они равны нулю, их не следует включать в словарь.
Для меня NSNull - такая же большая проблема, как и ее решение. При создании объектов NSDictionary для использования в других объектах вы можете пойти двумя путями, когда имеете дело со значениями nil. Либо вы добавляете объекты NSNull в свой словарь, а затем проверяете значения NSNull при чтении значений. Это делает красивый код на этапе создания, но становится грязным при считывании значений. Ex. Вы должны проверить все ключи в словаре, или некоторые гарантированно не равны нулю? И если значение NSNull не отфильтровано, оно обязано делать исключения при попытке отправить объектные сообщения.
Второй способ - просто не добавлять значения NSNull в словарь. Это удобно при чтении NSDictionary, так как [ someDictionary objectForKey: someKey ] просто возвращает nil, когда ключ не установлен. Такой подход делает это довольно просто при чтении значений, но он действительно должен быть грязным кодом при создании. Ex. Создание NSMutableDictionary, проверка на nil перед добавлением значений и, наконец, возвращение неизменяемой копии?
Решение
Для меня решение состояло в том, чтобы создать две категории, что, по сути, облегчает как создание, так и чтение.
При создании NSDictionary вы просто оборачиваете свои возможные значения-ноль, как это
[NSDictionary dictionaryWithObjectsAndKeysIngoringNull:
[NSNull nullWhenNil:val1], @"value1",
[NSNull nullWhenNil:val2], @"value2",
...
nil];
Этот код почти такой же простой, как и подход номер один, но он существенно облегчает считывание значений.
Категории следующие (работает как с включенным ARC, так и без кода ARC):
NSDictionary дополнение:
@implementation NSDictionary (NullAddition)
+ (id)dictionaryWithObjectsAndKeysIngnoringNull:(id)firstObject, ... {
NSMutableArray* objects = [NSMutableArray array];
NSMutableArray* keys = [NSMutableArray array];
va_list args;
va_start(args, firstObject);
for (id object = firstObject; object; object = va_arg(args, id)) {
id key = va_arg(args, id);
if (!key)
break;
if (![object isKindOfClass:[NSNull class]]) {
[objects addObject:object];
[keys addObject:key];
}
}
va_end(args);
return [self dictionaryWithObjects:objects forKeys:keys];
}
@end
NSNull дополнение
@implementation NSNull (NullAddition)
+ (id)nullWhenNil:(id)obj {
return (obj ? obj : [self null]);
}
@end
Удачи!
Попытка вставить данные (ключ или значение) в NSDictionary
приведет к ошибке времени выполнения. Следовательно, вам не нужно иметь дело с нулевыми данными в словаре.
'-[__NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: Test)'
а также
'-[__NSCFDictionary setObject:forKey:]: attempt to insert nil key'
Однако это означает, что вы несете ответственность за проверку достоверности данных перед их помещением в словарь для предотвращения сбоев.
Я столкнулся с аналогичной проблемой, и Google меня сюда. Мне нужно добавить в словарь kv, значение которого может быть нулевым. Вдохновленный ответом Тренскоу, я модифицирую эту функцию, чтобы поддерживать значение insert nil, а не завершать, как раньше.
#define KV_END NSNull.null
NSDictionary *NSDictionaryOfKV(id firstKey, ...) {
__auto_type dict = [NSMutableDictionary dictionary];
va_list args;
va_start(args, firstKey);
for (id key = firstKey; key != NSNull.null; key = va_arg(args, id)) {
id obj = va_arg(args, id);
if (obj == NSNull.null) {
break;
}
if (key) {
dict[key] = obj;
}
}
va_end(args);
return dict.copy;
}
__auto_type value2 = nil;
__auto_type dict = NSDictionaryOfKV(key1, value1, key2, value2, key3, value3, KV_END);
У тебя будет
{
key1: value1,
key3: value3
}
Вы можете изменить KV_END
к чему угодно.
Это имеет смысл, когда ваше значение является переменной, вы можете использовать его как есть, не нужно обертывать его или как value ?: NSNull.null
.