我们在初始化一个可变字典之后,再给其添加键值对的时候可以使用字典的setObject:forKey:
方法,或者使用kvc的方式。
setObject:forKey:
将给定的键值对添加到字典中
- (void)setObject:(ObjectType)anObject forKey:(id<NSCopying>)aKey
参数讲解:
anObject:
aKey
的值,对该对象的强引用由字典维护重点: 如果
anObject
为nil的话,会抛出NSInvalidArgumentException
异常,如果你想在字典中表示一个nil 值,可以使用NSNull
比如:
[dict setObject:[NSNull null] forKey:@"null"];打印:null = "<null>";
aKey:
value
的key
,aKey
将被复制(使用copyWithZone:
方法;key必须遵守NSCopying
协议),如果字典中存在了该key
,将替换anObject
重点: 如果key为nil的话,会抛出
NSInvalidArgumentException
异常
也就是使用setObject:forKey:
方法会对value
强引用,会使value
的引用计数加一。
NSMutableDictionary *dict = @{}.mutableCopy;
NSString *key = @"test";
NSMutableArray *arr = [[NSMutableArray alloc] init];
printf("after init retain count = %ld\n",CFGetRetainCount((__bridge CFTypeRef)(arr)));
[dict setObject:arr forKey:key];
printf("after setObject:forKey: retain count = %ld\n ",CFGetRetainCount((__bridge CFTypeRef)(arr)));
打印信息:
after init retain count = 1
after setObject:forKey: retain count = 2
字典的KVC
使用KVC的方式也可以为一个可变字典添加一个键值对,
- (void)setValue:(nullable ObjectType)value forKey:(NSString *)key;
value
可以为
nil
,当value
为nil
时,会调用字典的removeObjectForKey:
方法,不为nil
时,调用字典的setObject:forKey:
方法来添加键值对
key:
需要注意的是,当使用kvc的时候,
key
必须是字符串
kvc在引用计数环境下,直接访问实例变量的话,value
会被retain
,
NSMutableDictionary *dict = @{}.mutableCopy;
NSMutableArray *arr = [[NSMutableArray alloc] init];
printf("after init retain count = %ld\n",CFGetRetainCount((__bridge CFTypeRef)(arr)));
[dict setObject:arr forKey:@"test"];
printf("after setObject:forKey: retain count = %ld\n ",CFGetRetainCount((__bridge CFTypeRef)(arr)));
// kvc 方式添加键值对
[dict setValue:arr forKey:@"test2"];
printf("after kvc retain count = %ld\n ",CFGetRetainCount((__bridge CFTypeRef)(arr)));
打印:
after init retain count = 1
after setObject:forKey: retain count = 2
after kvc retain count = 3
总结:
相同点:
- 两个方法的
key
都不能为nil,否则抛出NSInvalidArgumentException
- 都会对
value
强引用
不同点
setObjec:forKey:
的key
必须遵守NSCopying
协议,KVC的key
必须为字符串setObjec:forKey:
的value
不能为空,否则会抛出NSInvalidArgumentException
异常; KVC的value
会nil时,会调用字典的removeObjectForKey:
方法,否则,调用字典的setObject:forKey:
方法添加键值对
取值
相应的,我们从字典中取值的时候,可以使用字典的objectForKey :
方法,也可以使用valueForKey:
方法。
这两种方法都比较简单,一般情况下,字典的valueForKey:
方法也是调用objectForKey :
来取值的,但这存在了一个前提:key
不能以字符"@"
开头
当key
不是以"@"
开始时,调用字典的objectForKey:
方法。如果以"@"
开始的话,则去除掉"@"
字符,并用剩余的字符调用[super valueForKey:]
方法。当父类也没有找到该key
时,会调用valueForUndefinedKey:
方法,而valueForUndefinedKey:
默认是抛出一个异常的。(只会去除开头的第一个"@"
,即如果key
是以多个"@"
字符开始的话,只会去除第一个开始的"@"
,剩余的"@"
字符会被保留)
NSMutableDictionary *dict = @{}.mutableCopy;
NSMutableArray *arr = [[NSMutableArray alloc] init];
NSString *key1 = @"@@@test";
[dict setObject:arr forKey:key1];
//取值
id test2 = [dict valueForKey:key1];
控制台打印:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSDictionaryM 0x600000222a80> valueForUndefinedKey:]: this class is not key value coding-compliant for the key @@test.'
可以看到,我们本来是通过"@@@test"
字符串作为key
去取值的,但是在查找过程中去除了第一个"@"
字符,用剩下的字符串"@@test"
去作为key
去查找的(不是把所有的"@"
字符去除)。
另外,与赋值时不同,取值时key
为nil
时并不会抛出异常。
删除
字典可以使用removeObjectForKey :
方法删除某个键值对
- (void)removeObjectForKey:(KeyType)aKey;
key为nil的话, 会抛出
NSInvalidArgumentException
异常
当字典中不存在该key的时候,则什么都没做。
removeAllObjects
清空字典里的数据,其实是向字典中每个key以及对应的value
发送release
消息
最后:
最近一段时间,公司项目被改了又改,几乎每个模块都被重写了几遍,心力憔悴。。。又在抽空学习HTML,几乎没时间总结iOS了,所以就拿经常用的知识点做了一点总结。