背景
NSMutableDictionary这个基础的数据类型在OC里大家经常使用,然而用的时候大家不知道有没有注意过,NSMutableDictionary的取值和存值是有两种不同的方式的。
NSMutableDictionary赋值
赋值一共有两个方法:
1. func setObject(_ anObject: Any, forKey aKey: NSCopying )
2. func setValue(_value:Any?,forKey key: String)
官方对他们的解释都是: 将给定的键值对添加到字典中。那么这两个方法有什么区别呢,我们看以下几个方面
参数
setObject(_ anObject: Any, forKey aKey: NSCopying)函数:
anObject: aKey的值。字典维护对对象的强引用。
aKey: 值的键。键被复制(使用copy(with:);键必须符合NSCopying协议)。如果字典中已经存在一个Key,则用anObject代替它。
setValue(_value:Any?,forKey key: String)函数:
value: 键的值。
key: 值的键。请注意,在使用键值编码时,键必须是字符串(请参见访问对象属性)。
这里有两点不同
1. setValue:forKey:中的key参数必须是一个字符串 而setObject:forKey:中的key参数可以是任何符合NSCopying协议的对象。
2. setObject:forKey:中的anObject参数是不能为nil的, 如果需要在字典中表示nil值,请使用NSNull,而 setValue:forKey:中的value参数则没有限制。
行为
还有什么不同呢?官方的注解中有一句话是:setValue:forKey:方法使用setObject:forKey:将值和键添加到字典中,除非值为零,在这种情况下,该方法会尝试使用removeObjectForKey:删除键。,也就是在值为nil的情况下,两者的行为是不同的
强调
这里要强调一点我们在上面说的setValue:forKey:方法是NSMutableDictionary的方法,是NSMutabledictionary特有的,而不是NSKeyValueCoding的主要方法setValue:forKey:,虽让他们的参数和函数名都一样。
比如:我们如果看官方文档,会发现NSKeyValueCoding中的setValue(_:forKey:)方法中的参数的含义分别是:
value: 键标识的属性的值。
key: 接收者属性之一的名称。
NSMutableDictionary取值
取值有两个方法:
1. - (ObjectType)valueForKey:(NSString *)key;
2. - (ObjectType)objectForKey:(KeyType)aKey;
他们的作用都是: 返回与给定键关联的值。我们看一下两个方法的不同:
参数
valueForKey:方法的参数在使用键值编码时,键必须是字符串(请参见访问对象属性)
行为
两个方法返回的是与aKey关联的值,如果没有值与aKey关联,则为nil, 但是valueForKey:方法中,如果键不是以“@”开头,则调用objectForKey:。如果键以“@”开头,则去掉“@”并用键的其余部分调用[super valueForKey:]。假设我们有如下代码,那么会发生什么事情呢?
NSDictionary *dic = [NSDictionary dictionaryWithObject:@"value" forKey:@"@key"];
id value1 = [dic objectForKey:@"@key"];
id value2 = [dic valueForKey:@"@key"];
大家知道value1是什么吗? 是"value"这个字符串,这个大家容易理解,因为存的时候就是"key"这个键对应“value”这个字符串。
那么value2是什么呢?答案是"@key"这个字符串。说到这里有同学怕是要拍案而起了,因为按照kvc的理论:valueForKey:这个方法返回由key参数命名的属性的值。如果根据访问者搜索模式中描述的规则找不到由键命名的属性,则该对象会向自己发送一条valueForUndefinedKey:消息。valueForUndefinedKey:的默认实现引发NSUndefined KeyException,但子类可能会覆盖此行为并更优雅地处理此情况。
实际上,这里我们可以试试将
NSDictionary *dic = [NSDictionary dictionaryWithObject:@"value" forKey:@"@key"];
这个NSDictionary的key换成任何的字符串,你会发现,都会产生NSUndefined KeyException。那么为什么"@key"字符串不会呢,大家可以看看对应的NSDictionary的源码,就会发现这个奥秘了。(如果还没有懂,请来问哦)
总结:
有些东西,一定要自己多看文档,才会了解其中的精髓,只停留在大概差不多的水平的话,那就躺平了。
网友评论