KVC与Json Model

KVC是动态获取或设置对象属性/成员变量的方法。就是我们常见的valueForKey:setValue:forKey:

KVC还支持集合操作和key path,个人认为这有点炫技成分。
官方文档:https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueCoding/index.html#//apple_ref/doc/uid/10000107-SW1

经常用到KVC的地方有:

  1. 访问成员变量。
  2. xib。控件的所有属性不可能都显示在面板里,User Define Runtime Attributes就是通过KVC来设置
  3. Dictionary <-> Object。

Dictionary <-> Object

KVC在这个场景特别流行,setValuesForKeysWithDictionary:功不可没。

- (id)initWithDictionary:(NSDictionary *)jsonDic
{
    self = [super init];
    
    if (self != nil)
    {
        [self setValuesForKeysWithDictionary:jsonDic];
        int i;
        unsigned int propertyCount = 0;
        objc_property_t *propertyList = class_copyPropertyList([self class], &propertyCount);
        
        for ( i=0; i < propertyCount; i++ )
        {
            objc_property_t *thisProperty = propertyList + i;
            
            const char* propertyName = property_getName(*thisProperty);
            
            NSString *propertyKeyName = [NSString stringWithUTF8String:propertyName];
            
            if ([[jsonDic valueForKey:propertyKeyName] isKindOfClass:[NSDictionary class]])
            {
                id object = [[[self getItemClassWithPropretyName:propertyKeyName] alloc] initWithDictionary:[jsonDic valueForKey:propertyKeyName]];
                [self setValue:object forKey:propertyKeyName];
            }
            else if ([[jsonDic valueForKey:propertyKeyName] isKindOfClass:[NSArray class]])
            {
                NSMutableArray *arr = [NSMutableArray array];
                for (id object in [jsonDic valueForKey:propertyKeyName])
                {
                    if ([object isKindOfClass:[NSDictionary class]])
                    {
                        [arr addObject:[[[self getItemClassWithPropretyName:propertyKeyName] alloc] initWithDictionary:object]];
                    }
                    else
                    {
                        [arr addObject:object];
                    }
                }
                [self setValue:arr forKey:propertyKeyName];
            }
        }
    }
    
    return self;
}

-(Class)getItemClassWithPropretyName:(NSString *)name
{
    // 检查 Class 是否实现了 initWithDictionary: 
}

setValuesForKeysWithDictionary: 处理不了集合类型,所有以得单独处理。

性能

KVC的搜索还挺复杂的

对于setValue:属性值 forKey:@"name";代码,底层的执行机制如下:

(1).程序优先调用“setName:属性值;”代码通过setter方法完成设置。
(2).如果该类没有setName:方法,KVC机制会搜索该类名为_name的成员变量,找到后对_name成员变量赋值。
(3).如果该类既没有setName:方法,也没有定义_name成员变量,KVC机制会搜索该类名为name的成员变量,找到后对name成员变量赋值。
(4).如果上面3条都没有找到,系统将会执行该对象的setValue: forUndefinedKey:方法。默认setValue: forUndefinedKey:方法会引发一个异常,将会导致程序崩溃。
对于“valueForKey:@"name";”代码,底层执行机制如下:

(1).程序优先调用"name;"代码来获取该getter方法的返回值。
(2).如果该类没有name方法,KVC机制会搜索该类名为_name的成员变量,找到后返回_name成员变量的值。
(3).如果该类既没有name方法,也没有定义_name成员变量,KVC机制会搜索该类名为name的成员变量,找到后返回name成员变量的值。
(4).如果上面3条都没有找到,系统将会执行该对象的valueForUndefinedKey:方法。默认valueForUndefinedKey:方法会引发一个异常,将会导致程序崩溃。

性能差于直接调用 Getter/Setter,如果能直接访问 ivar效率更高。

Refrence

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • KVC(Key-value coding)键值编码,单看这个名字可能不太好理解。其实翻译一下就很简单了,就是指iO...
    黑暗中的孤影阅读 49,927评论 74 441
  • KVC(Key-value coding)键值编码,单看这个名字可能不太好理解。其实翻译一下就很简单了,就是指iO...
    Fendouzhe阅读 684评论 0 6
  • KVC(Key-value coding)键值编码,iOS的开发中,可以允许开发者通过Key名直接访问对象的属性,...
    CALayer_Sai阅读 2,538评论 0 4
  • 简介 KVC(Key-value coding)键值编码,翻译一下就是指iOS的开发中,可以允许开发者通过Key名...
    6ffd6634d577阅读 1,328评论 1 9
  • KVC简单介绍 KVC(Key-value coding)键值编码,就是指iOS的开发中,可以允许开发者通过Key...
    公子无礼阅读 1,416评论 0 6