美文网首页
字典的KVC与setObject:forKey:的区别

字典的KVC与setObject:forKey:的区别

作者: 哆啦_ | 来源:发表于2018-04-19 15:30 被阅读237次

    我们在初始化一个可变字典之后,再给其添加键值对的时候可以使用字典的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:

    valuekey,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,当valuenil时,会调用字典的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

    总结:
    相同点:

    1. 两个方法的key都不能为nil,否则抛出NSInvalidArgumentException
    2. 都会对value强引用

    不同点

    1. setObjec:forKey:key必须遵守NSCopying协议,KVC的key必须为字符串
    2. 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去查找的(不是把所有的"@"字符去除)。

    另外,与赋值时不同,取值时keynil时并不会抛出异常。

    删除

    字典可以使用removeObjectForKey :方法删除某个键值对

    - (void)removeObjectForKey:(KeyType)aKey;
    

    key为nil的话, 会抛出NSInvalidArgumentException异常
    当字典中不存在该key的时候,则什么都没做。

    removeAllObjects
    清空字典里的数据,其实是向字典中每个key以及对应的value发送release消息


    最后:
    最近一段时间,公司项目被改了又改,几乎每个模块都被重写了几遍,心力憔悴。。。又在抽空学习HTML,几乎没时间总结iOS了,所以就拿经常用的知识点做了一点总结。

    相关文章

      网友评论

          本文标题:字典的KVC与setObject:forKey:的区别

          本文链接:https://www.haomeiwen.com/subject/jtkbkftx.html