Безопасная подписка на NSDictionary

С синтаксисом литералов можно использовать словарь NSDictionary *, подобный этому, чтобы получить objectForKey

NSDictionary * dictionary;
id object = dictionary[key];

Но если тип словаря имеет тип ID, и вы пытаетесь написать

id dictionary;
id object = dictionary[key];

Это будет работать до тех пор, пока ваш словарь не станет действительно словарём, иначе он зависнет.

Решением для этого было бы иметь метод

-(id)safeObject:(id)object forKey:(id)aKey {
    if (![object isKindOfClass:[NSDictionary class]]) {
        return nil;
    }
    return [object objectForKeyedSubscript:aKey];
}

Так что теперь, когда я называю это так

id dictionary;
id object = [self safeObject:dictionary forKey:key];

Это не потерпит крах. Но проблема с этим в том, что если мне нужно углубиться, например, во вложенный словарь

id object = dictionary[key1][subKey1][subsubKey1];

Это действительно удобно писать с буквальным синтаксисом со старым синтаксисом, это было бы что-то вроде

id mainObject = [self safeObject:dictionary forKey:key1];
id subObject = [self safeObject:mainObject forKey:subKey1];
id object = [self safeObject:subObject forKey:subsubKey1];  

Так что не так много читабельно. Я хочу иметь это решение с новым литеральным синтаксисом, возможно ли это?

1 ответ

Вы могли бы использовать valueForKeyPathнапример,

id dictionary = @{@"key":@{@"subkey" : @{ @"subsubkey" : @"value"}}};
id object = [self safeObject:dictionary];
id value = [object valueForKeyPath:@"key.subkey.subsubkey"];

Также немного измените safeObject только для проверки, является ли это словарь,

- (id)safeObject:(id)object {
    if (![object isKindOfClass:[NSDictionary class]]) {
        return nil;
    }
    return object;
}

Надеюсь, это поможет, это то, что вы ищете?

Другие вопросы по тегам