在 NSMutableDictionary 和 NSUserDefaults 的分类中,可以通过键路径来设置嵌套对象。
我经常想在一个可变的字典中设置多层深度的值。不幸的是,如果嵌套的可变字典不存在,这将失败。以下语句输出 null
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[@"a"][@"b"] = @"foo";
NSLog(@"%@", dict[@"a"][@"b"]);
稍微重写这个语句可以使其更明显
[[dict objectForKey:@"a"] setObject:@"foo" forKey:@"b"];
第一个 objectForKey:
方法返回 nil,接下来的 setObject:ForKey:
会静默失败。
另一个常见的用例是当我对一个字典进行可变副本时 - 任何包含在字典中的字典仍然保持不可变,这导致了像这样的恼人、易出错的代码来简单地在除了根级别之外的地方设置新的值
NSDictionary *colorSets = @{
@"ColorsOfTheRainbow": @{
@"Red": @"#F00",
@"Yellow": @"#FF0",
@"Pink": @"#F0F",
@"Green": @"#0F0",
@"Purple": @"#8000FF",
@"Orange": @"#F80"
}
};
/* Create mutable copy of dictionary */
NSMutableDictionary *newColorSets = [colorSets mutableCopy];
/* Get second-level dictionary */
NSDictionary *currentColorsOfTheRainbow = [colorSets objectForKey:@"ColorsOfTheRainbow"];
/* Check that the second level dictionary existed. If so - create a mutable copy; if not - create a new mutable dictionary to use */
NSMutableDictionary *newColorsOfTheRainbow = (currentColorsOfTheRainbow) ? [currentColorsOfTheRainbow mutableCopy] : [NSMutableDictionary dictionary];
/* Set the value in the new dictionary */
[newColorsOfTheRainbow setObject:@"#00F" forKey:@"Blue"];
/* Set the second-level dictionary back into the mutable dictionary */
[newColorSets setObject:newColorsOfTheRainbow forKey:@"ColorsOfTheRainbow"];
以下两个实例方法被添加到 NSMutableDictionary
和 NSUserDefaults
- (void)setObject:(id)object forKeyPath:(NSString *)keyPath;
- (void)setObject:(id)object
forKeyPath:(NSString *)keyPath
createIntermediateDictionaries:(BOOL)createIntermediates
replaceIntermediateObjects:(BOOL)replaceIntermediates;
第一个是一个方便方法,传入第二个参数的 YES
- 这可能是最想要的行为。
createIntermediateDictionaries
在遍历键路径时创建任何必要的非存在的字典。replaceIntermediateObjects
替换键路径中返回的任何非 NSDictionary
子类的对象。上面的例子可以用以下代码简单实现
[dict setObject:@"foo" forKeyPath:@"a.b"];
和
[newColorSets setObject:@"#00F" forKeyPath:@"ColorsOfTheRainbow.Blue"];
方法默认以 nos_
为前缀,以避免任何名称空间冲突。
要使用不带前缀的方法,请将 NESTEDOBJECTSETTERS_NO_PREFIX = 1
添加到项目的前缀文件,或将 NESTEDOBJECTSETTERS_NO_PREFIX=1
添加到目标的构建设置中的预处理器宏部分。
这些分类与 ARC 和传统的保留/释放代码都兼容,并且可以在所有版本的 iOS 和 OS X 上使用。
NestedObjectSetters.h/m
添加到您的项目中。pod 'NestedObjectSetters'