iOS进阶-10 KVC

在日常发开中,我们可以通过断点调试、源码查看、LLDB调试来探索技术的原理,其实文档查看也是一种极其重要的手段。
KVC(Key-Value Coding)是我们日常开发中常见的一种技术,那么底层又是如何实现的呢?我们先看官方文档Key-Value Coding Programming Guide,当然你可以在文档首页搜索其他技术的文档Apple Documentation Archive

KVC简介

Key-value coding is a mechanism enabled by the NSKeyValueCoding informal protocol that objects adopt to provide indirect access to their properties.
可以在文档上看到:KVC是一种能够通过NSKeyValueCoding协议直接访问对象属性的机制。

getter方法- valueForKey:

  • 1.寻找是否有这些方法get<Key>, <key>, is<Key>, or _<key>,如果有跳到5,没有走下一步
  • 2.判断是否是NSArray
  • 2.1寻找是否实现countOf<Key>或者objectIn<Key>AtIndex: 方法,有的话就调用方法并返回值,没有就走3
  • 3.是否是NSSet
  • 3.1 寻找是否实现countOf<Key>, enumeratorOf<Key>, and memberOf<Key>:方法,有的话就调用方法并返回值,没有就走4·
  • 4.非集合类型
    • 4.1 判断accessInstanceVariablesDirectly:(是否可以直接访问成员变量:默认返回YES)方法是否返回YES
    • 4.2寻找_<key>, _is<Key>, <key>, or is<Key>这些成员变量
    • 4.3如果找到,直接获取实例变量的值,然后执行步骤5
  • 5.细节处理
    • 5.1如果检索到的属性值是对象指针,则只需要返回结果
    • 5.2如果该值是NSNumber支持的标量类型,则将其存储在NSNumber实例中并返回
    • 5.3如果该值是NSNumber不支持的标量类型,则转化为NSValue对象并返回
  • 6.报错 valueForUndefinedKey:

setter方法- setValue:forKey:

  • 1.简单式访问:寻找是否存在set<Key>:或者 _set<Key>的方法,如果有,那就调用,并完成;如果没有进入2
  • 2.实例变量访问:
    • 2.1 判断这个方法accessInstanceVariablesDirectly是否返回YES
    • 2.2 判断是否存在这些实例变量_<key>, _is<Key>, <key>, or is<Key>
    • 2.3 按顺序找到就直接赋值,并完成,不再给下面的成员变量赋值
  • 3.报错:如果1和2都有找到,那么就报错:setValue:forUndefinedKey:

KVC其他功能

1.自动转换类型

在存值时如果value的类型是NSString类的数字、结构体类型,取值时value类型会进行相应的转化成__NSCFNumber 、NSConcreteValue。eg:
Person类实现

typedef struct {
    float x, y, z;
} ThreeFloats;

@interface Person : NSObject
@property (nonatomic, copy) NSString *subject;
@property (nonatomic, assign) int  age;
@property (nonatomic, assign) BOOL sex;
@property (nonatomic) ThreeFloats  threeFloats;

@end

调用

Person *person = [[Person alloc] init];

// 1: KVC 自动转换类型
    NSLog(@"******1: KVC - int -> NSNumber - 结构体******");

    [person setValue:@18 forKey:@"age"];
    // 上面那个表达 大家应该都会! 但是下面这样操作可以?
    [person setValue:@"20" forKey:@"age"]; // int - string
    NSLog(@"%@-%@",[person valueForKey:@"age"],[[person valueForKey:@"age"] class]);//__NSCFNumber
    
    [person setValue:@"20" forKey:@"sex"];//Bool - string
    NSLog(@"%@-%@",[person valueForKey:@"sex"],[[person valueForKey:@"sex"] class]);//__NSCFNumber

    ThreeFloats floats = {1., 2., 3.};
    NSValue *value  = [NSValue valueWithBytes:&floats objCType:@encode(ThreeFloats)];
    [person setValue:value forKey:@"threeFloats"];
    NSLog(@"%@-%@",[person valueForKey:@"threeFloats"],[[person valueForKey:@"threeFloats"] class]);//NSConcreteValue
设置空值
    NSLog(@"******2: 设置空值******");
    [person setValue:nil forKey:@"age"]; //age 为nil
    [person setValue:nil forKey:@"subject"];//subject不会走 - 官方注释里面说只对 NSNumber - NSValue,而NSString类型没有这个功能
找不到的 key
    NSLog(@"******3: 找不到的 key******");
    [person setValue:nil forKey:@"KC"]; 
取值时 - 找不到 key
    NSLog(@"******4: 取值时 - 找不到 key******");
    NSLog(@"%@",[person valueForKey:@"KC"]);
键值验证

KVC提供键值验证api
- (BOOL)validateValue:(inout id _Nullable * _Nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;

    NSLog(@"******5: 键值验证******");
    NSError *error;
    NSString *name = @"Cooci";
    if (![person validateValue:&name forKey:@"names" error:&error]) {
        NSLog(@"%@",error);
    }else{
        NSLog(@"%@",[person valueForKey:@"name"]);
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容