1、总结
- setValue和valueForKey是KVC的主要方法,setObject和objectForKey是NSMutableDictionary的特性;
- setValue和valueForKey的KVC方式,相比NSMutableDictionary的特性的好处就是setValue时,value可以为nil。不好的是key只能字符串类型,否则valueForKey取值时会崩溃;
- objectForKey和setobject的NSMutableDictionary的特性,相比KVC的好处是Key可以为任意类型,不好的就是value不能nil,否则setObject的时候会崩溃
- 共同点是,key值都不能为nil
- 在实际使用的时候,想要保证安全性,达到以下条件才可取值或set
- set设置值时
- setobject:key和value都不能为nil且是可变字典【key!= nil && value != nil && [dic isKindOfClass:[NSMutableDictionary Class]]】
- setValue: key为字符串类型且为可变字典【[key isKindOfClass:[NSString string]] && [dic isKindOfClass:[NSMutableDictionary Class]]】
- ForKey取值时
- objectForKey:key不能为nil【key!= nil】
- valueForKey: key为字符串类型【[key isKindOfClass:[NSString string]]】
- set设置值时
2、具体分析
2.1、NSMutableDictionary的特性 【setobject和objectForKey】
Value 可以为除了nil外的任何对象
-
Key 可以为除了nil外的任何对象【即key不可为nil,为nil直接崩溃,但是可以为其他任意类型的对象,如:空字符串@"",空对象[NSNull null],其他类型的对象(如数组)】
setobject中的key除了不能为nil,其他都可以
objectForKey中的Key除了不能为nil,其他都可以
示范
// Value 示范
NSArray *arry = [NSArray arrayWithObject:[NSNumber numberWithInteger:888888]];
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setObject:@"2" forKey:@"keyStr1"];
[dic setObject:@"" forKey:@"keyStr2"];
[dic setObject:[NSNull null] forKey:@"keyStr3"];
[dic setObject:arry forKey:@"keyStr5"];
// [dic setObject:nil forKey:@"keyStr4"]; // [崩溃]
// 结果 Value不能为nil
(lldb) po dic
{
keyStr1 = 2;
keyStr2 = "";
keyStr3 = "";
keyStr5 = (
888888
);
}
// Key 示范
NSArray *arry = [NSArray arrayWithObject:[NSNumber numberWithInteger:888888]];
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
//1、key 为空对象[NSNull null]
[dic setObject:@"1" forKey:[NSNull null]]; //【不崩溃+有警告】
[dic objectForKey:[NSNull null]]; //字典属性取值,能取出值 【不崩溃】
// [dic valueForKey:[NSNull null]];//KVC取值 【崩溃】
//2、key 为nil
// [dic setValue:@"3" forKey:nil]; //崩溃
//3、key 为非字符串对象 arry
[dic setObject:@"4" forKey:arry];//【不崩溃+有警告】
[dic objectForKey:arry]; //字典属性取值,能取出值 【不崩溃】
// [dic valueForKey:arry];//KVC取值 【崩溃】
//4、key 为空字符串@“”
[dic setObject:@"2" forKey:@""]; //【不崩溃】
[dic objectForKey:@""]; //字典属性取值 能取出值 【不崩溃】
[dic valueForKey:@""];//KVC取值 能取出值 【不崩溃】
//5、key 为字符串
[dic setObject:@"5" forKey:@"number"]; //【不崩溃】
[dic objectForKey:@"number"]; //字典属性取值,能取出值 【不崩溃】
[dic valueForKey:@"number"];//KVC取值 能取出值 【不崩溃】
//结果
(lldb) po dic
{
"" = 1;
}
(lldb) po [dic objectForKey:[NSNull null]]
1
(lldb) po [dic valueForKey:[NSNull null]]
error: cannot initialize a parameter of type 'NSString * _Nonnull' with an rvalue of type 'NSNull * _Nonnull'
passing argument to parameter 'key' here
(lldb) po [dic setValue:@"3" forKey:nil]
error: Execution was interrupted, reason: internal ObjC exception breakpoint(-4)..
The process has been returned to the state before expression evaluation.
(lldb) po dic
{
"" = 1;
(
888888
) = 4;
}
(lldb) po [dic objectForKey:arry]
4
(lldb) po [dic valueForKey:arry]
error: cannot initialize a parameter of type 'NSString * _Nonnull' with an lvalue of type 'NSArray *'
passing argument to parameter 'key' here
(lldb) po [dic setObject:@"2" forKey:@""]
error: cannot initialize a parameter of type 'id _Nonnull' with an rvalue of type 'NSString *'
passing argument to parameter 'aKey' here
(lldb) po [dic objectForKey:@""]
nil
(lldb) po [dic valueForKey:@""]
nil
(lldb) po dic
{
"" = 2;
(
888888
) = 4;
number = 5;
"" = 1;
}
(lldb) po [dic objectForKey:@"number"]
5
(lldb) po [dic valueForKey:@"number"]
5
(lldb)
2.2、 KVC 【setValue和valueForKey】
Value 可以为nil也可以为空对象[NSNull null]以及全部对象
-
Key 只能为字符串包括空字符串,不能为其他对象
setValue中的key除了不能为nil,其他都可以【如:[NSNull null],arry,@"",@"keystr"】
valueForKey中的key只能为字符串包括空字符串@"",不能为其他的【即nil或其他类型】,其他一律崩溃
所以综上所述如果用KVC的方法setValue和valueForKey来使用dic,通常说Key只能为字符串包括空字符串。所以在实际应用中使用KVC来使用字典只要判断key是否为string对象,就可以做到相应的读写安全【可变数组set之前还需要判断是否为可变字典】
示范
// Value 示范
NSArray *arry = [NSArray arrayWithObject:[NSNumber numberWithInteger:888888]];
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setValue:@"2" forKey:@"keyStr1"];
[dic setValue:@"" forKey:@"keyStr2"];
[dic setValue:[NSNull null] forKey:@"keyStr3"];
[dic setValue:nil forKey:@"keyStr4"];
[dic setValue:arry forKey:@"keyStr5"];
// 结果 都set成功
(lldb) po dic
{
keyStr1 = 2;
keyStr2 = "";
keyStr3 = "";
keyStr5 = (
888888
);
}
// Key 示范
NSArray *arry = [NSArray arrayWithObject:[NSNumber numberWithInteger:888888]];
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
//1、key 为空对象[NSNull null]
[dic setValue:@"1" forKey:[NSNull null]]; //【不崩溃+有警告】
[dic objectForKey:[NSNull null]]; //字典属性取值,能取出值 【不崩溃】
// [dic valueForKey:[NSNull null]];//KVC取值 【崩溃】
//2、key 为nil
// [dic setValue:@"3" forKey:nil]; //崩溃
//3、key 为非字符串对象 arry
[dic setValue:@"4" forKey:arry];//【不崩溃+有警告】
[dic objectForKey:arry]; //字典属性取值,能取出值 【不崩溃】
// [dic valueForKey:arry];//KVC取值 【崩溃】
//4、key 为空字符串@“”
[dic setValue:@"2" forKey:@""]; //【不崩溃】
[dic objectForKey:@""]; //字典属性取值 能取出值 【不崩溃】
[dic valueForKey:@""];//KVC取值 能取出值 【不崩溃】
//5、key 为字符串
[dic setValue:@"5" forKey:@"number"]; //【不崩溃】
[dic objectForKey:@"number"]; //字典属性取值,能取出值 【不崩溃】
[dic valueForKey:@"number"];//KVC取值 能取出值 【不崩溃】
// 结果 都set成功
(lldb) po dic
{
"" = 1;
}
(lldb) po [dic objectForKey:[NSNull null]]
1
(lldb) po [dic valueForKey:[NSNull null]] // 【崩溃】
error: cannot initialize a parameter of type 'NSString * _Nonnull' with an rvalue of type 'NSNull * _Nonnull'
passing argument to parameter 'key' here
(lldb) po [dic setValue:@"3" forKey:nil] 【崩溃】
error: Execution was interrupted, reason: internal ObjC exception breakpoint(-4)..
The process has been returned to the state before expression evaluation.
(lldb) po dic
{
(
888888
) = 4;
"" = 1;
}
(lldb) po [dic objectForKey:arry]
4
(lldb) po [dic valueForKey:arry] 【崩溃】
error: cannot initialize a parameter of type 'NSString * _Nonnull' with an lvalue of type 'NSArray *'
passing argument to parameter 'key' here
(lldb) po dic
{
"" = 2;
(
888888
) = 4;
"" = 1;
}
(lldb) po [dic objectForKey:@""]
2
(lldb) po [dic valueForKey:@""]
2
(lldb) po dic
{
"" = 2;
(
888888
) = 4;
number = 5;
"" = 1;
}
(lldb) po [dic objectForKey:@"number"]
5
(lldb) po [dic valueForKey:@"number"]
5
(lldb)