iOS KVC与KVO

KVC、KVO概述

  • KVC(NSKeyValueCoding) "键-值 编码"是一种间接访问对象的属性的机制,在Object2.0之后系统提供了(.)语法来访问属性,在此之前我们需要用KVC来访问。
  • KVO(NSKeyValueObserving) "键-值 监听"定义了这样一种机制,当对象属性值发生变化的时候我们能收到一个通知。
    注:NSObject类为所有对象提供了一个自动观测能力的NSKeyValueObserving协议。你可以根据具体需求来打开这个监听机制。KVO是根据KVC来实现的。

KVC、KVO的作用

  • KVC是一种间接访问对象属性的机制。
    获取属性值时可以通过valueForKey:的方法,设置属性值用setValue: forKey:。与此同时KVC还对未定义的属性值定义了valueForUnderfineKey:,在这里我们需要注意的是KVC中的value都必须是对象。我们可以通过KVC给在m文件中声明的属性进行操作,前提是,我们必须知道这个属性的属性名。
  • KVO是基于KVC来实现的。
    系统已经为我们提供了相关的方法,我们只需要注册这个监听,就能很好的监听属性的值发生改变。
  • 注册:下面的方法中,keyPath就是要观察的属性值,options提供的是一个枚举值,就是当键值变化是你可以选择不同的方式,context方便传输你需要的数据。
-(void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:
(NSKeyValueObservingOptions)options context:(void *)context
  • 实现监听方法:其中change里储存了一些数据的变化,比如变化前的数据,变化后的数据。
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:
(NSDictionary<NSString *,id> *)change context:(void *)context

KVC键-值 编码

KVC的实现机制

KVC会顺序使用如下技术

  • 检查是否存在getter方法-<Key>或者setter方法-set<Key>的方法。
  • 如果没有上述方法,则检查是否存在名字为—_<Key>、<Key>的实例变量。
  • 如果仍未找到,则调用valueForUnderfineKey和setValue:forUnderfineKey:方法。这些方法的默认实现都是抛出异常,我们可以根据需要重写他们。

示例代码

//使用KVC进行属性的间接访问
Person *aperson = [[Person alloc]init];
[aperson setValue:@"Duck" forKey:@"name"];//等效于aperson.name = @"Duck";
[aperson setValue:@"male" forKey:@"gender"];//等效于aperson.sex = @"male";
Student *astudent = [[Student alloc]init];
[aperson setValue:astudent forKey:@"student"];//通过键值的方式为student属性赋值
[aperson setValue:@"Leo" forKeyPath:@"student.name"];//键路径:通过这个方法可以对属性的属性进行操作。
setValuesForKeysWithDictionary:<#(nonnull NSDictionary<NSString *,id> *)#>

使用这个方法可以将字典里的键值快速的赋值给属性,但是一定要保证属性的名字和字典的键是一致的。如果字典的键多余属性那么就需要我们在这个属性的类中实现下面的一个方法。

-(void)setValue:(id)value forUndefinedKey:(NSString *)key

KVO键-值 监听者

KVO key - value - observer 观察者观察的是属性是否执行了set方法或者是属性是否使用了KVC赋值,只要有赋值的动作,都会执行KVO的回调方法。如果赋值没有通过set方法或者例如(_name = @"新值",就不会出发KVO回调方法,一般KVO崩溃的原因有两种,第一个原因,被观察的对象是一个局部变量,它已经被销毁掉了。第二个原因,观察者被释放掉了,但是没有移除监听。3,注册的监听没有移除掉,又重新注册了监听)。
首先我们需要注册一个观察者,示例代码如下

[self.view addObserver:self forKeyPath:@"backgroundColor" options:
NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];

options几个枚举选项的意思

NSKeyValueObservingOptionOld 把更改之前的值提供给处理方法
NSKeyValueObservingOptionNew 把更改之后的值提供给处理方法
NSKeyValueObservingOptionInitial 把初始化的值提供给处理方法,一旦注册,立马就会调用一次。通常它会带有新值,而不会带有旧值。
NSKeyValueObservingOptionPrior 分2次调用。在值改变之前和值改变之后。
  • observer:观察者(观察对象属性的变化)
  • KeyPath:被观察属性的名称
  • options:观察属性的新值旧值等一些的配置
  • context:可以为KVO的回调方法传值。

KVO的回调方法
当同时监听多个属性的时候,我们需要判断

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
    if ([keyPath isEqualToString:@"backgroundColor"]) {//view的背景颜色发生了变化
        id oldColour = [change objectForKey:NSKeyValueChangeOldKey];
        id newcolour = [change objectForKey:NSKeyValueChangeNewKey];
        NSLog(@"%@,old==%@",NSKeyValueChangeOldKey,oldColour);
        NSLog(@"%@,new==%@",NSKeyValueChangeNewKey,newcolour);
    }
    if ([keyPath isEqualToString:@"name"]) {
        id oldValue = [change objectForKey:NSKeyValueChangeOldKey];
        id newValue = [change objectForKey:NSKeyValueChangeNewKey];
        NSLog(@"%@",oldValue);
        NSLog(@"%@",newValue);
    }
}
  • keyPath:属性名称
  • object:被观察的对象
  • change:变化前后的值都存储在字典中
  • context:注册观察者的时候context传过来的值

移除监听的方法
一定要在我们不需要监听的时候,移除监听,不然可能会造成程序崩溃。

- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:
(nullable void *)context NS_AVAILABLE(10_7, 5_0);
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

至此有关于KVC和KVO的相关知识解释完成,还有其他不足之处,欢迎提出意见。

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

推荐阅读更多精彩内容

  • 1.KVC 关于 KVC 和 KVO ,我之前的总结文章有写过,但是趋于表面,没有探究其内部真正的实现原理和进阶用...
    Liberalism阅读 1,071评论 0 5
  • 本文结构如下: Why? (为什么要用KVO) What? (KVO是什么) How? ( KVO怎么用) Mo...
    等开会阅读 1,635评论 1 21
  • 在编程中,最常见的就是程序的流程取决于你所使用的各种变量和属性的值,根据变量和属性的值确定后面运行的代码,有时会检...
    pro648阅读 1,633评论 2 27
  • 上半年有段时间做了一个项目,项目中聊天界面用到了音频播放,涉及到进度条,当时做android时候处理的不太好,由于...
    DaZenD阅读 3,009评论 0 26
  • 恐惧越多, 越需要诺言来提供保证。 但真相是, 背叛,往往是因许诺而生的。 忠于每一个当下 不被过去所累 不被未来...
    一个壶阅读 129评论 1 0