iOS消息传递之KVO

  KVO简介:键值观察,是基于键值编码(KVC)的一种观察模式。 是iOS中常用的一种消息传递机制。
  对接模式:发送者和接收者的关系为一对多的关系,一个发送者可以有多个接收者。
  使用键值观察需要被观察对象编写符合KVC标准的存取方法,使用步骤分为以下三步:

  • 第一步:注册成为KVO观察者
  • 第二步:定义KVO的回调
  • 第三步:移除KVO观察者
      第一步:调用注册方法成为观察者
[ObjectOfObserved addObserver:observerObject forKeyPath:@"example" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];

KVO注册方法参数:

  • ObjectOfObserved:NSObject类型,为被观察者对象
  • 参数Observer:NSObject类型,为观察者对象,即要注册成为观察者的对象(既然是在观察者的.m文件中实现的,那么该参数则为self)
  • 参数KeyPath:NSString类型,键路径参数,描述将要观察的属性,即被观察者的属性参数。(如:被观察者有一个命名为example的属性,而且你要观察的正是这个属性,那就设置这个参数为@"example")
  • 参数options:枚举类型,有四个选项,标识KVO希望变化如何传递给观察者,可以使用"|"进行多选(这里观察属性变化的新值和旧值)

options枚举:
1、NSKeyValueObservingOptionNew:该枚举值保证KVO监听属性的新内容,当属性内容变化时,KVO会记录属性的新内容,这样KVO回调方法中的参数change字典中包括改变后的值,可以通过KVO的监听回调方法获取到属性的新内容
2、NSKeyValueObservingOptionOld:该枚举值保证KVO监听属性的原内容,当属性内容变化时,KVO会记录属性的原内容,这样KVO回调方法中的参数change字典包括改变前的值,可以通过KVO的监听回调方法获取到属性的原内容
3、NSKeyValueObservingOptionInitial: 注册后立刻触发KVO通知,添加该枚举后,即使属性值没有变化,也会调用KVO回调方法
4、NSKeyValueObservingOptionPrior:值改变前是否也要通知(这个key决定了是否在改变前改变后通知两次)

  • 参数context:void类型指针,上下文内存区,通常设置为nil 。这个会传递到观察者的函数中,用来区分不同的监听消息。

如何设置context:
可以参考这篇文章Key-Value Observing中《正确的上下文声明》部分;以及这篇文章 kvo/gcd中关于context指针的赋值

  第二步:在观察者的.m实现文件中定义KVO的回调方法

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
}

该方法是系统提供的观察者实现键值观察方法,作为观察者,需要实现这个方法。当被观察的被观察属性发生变化时(这里的变化是指赋值操作,只要给属性赋值就会调用,就算赋相同的内容,也会调用),会自动调用这个方法。

KVO回调方法中参数:

  • 参数keyPath:NSString类型,被监听的keyPath , 用来区分不同的KVO监听
  • 参数object:id类型,为被监察的对象
  • 参数change:NSDictionary类型,保存被监察者信息的字典
  • 参数context:void类型,上下文,用来区分不同的KVO监听

KVO回调方法操作:

  • 当监听者监听了多个被监听者时,可以在回调方法中通过参数keyPath来判断是哪个监听消息,```
    [keyPath isEqualToString:@"name"]
* 获取被监听者对象```
    监听者对象类型 *变量名 = object;
  • 获取被监听者内容未变时的属性对象```
    属性对象类型 * old = [change objectForKey:NSKeyValueChangeOldKey];
* 获取被监听者内容已变时的属性对象```
属性对象类型 * new = [change objectForKey:NSKeyValueChangeNewKey];

  第三步:在观察者的.m文件中的dealloc方法中移除观察者

- (void)dealloc {
    // 调用移除观察者的方法:- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
    [ObjectOfObserved removeObserver:Observer forKeyPath:@"example"];
}

KVO移除方法参数:

  • ObjectOfObserved:NSObject类型,为被观察者对象
  • 参数Observer:NSObject类型,为观察者对象,即要注册成为观察者的对象(既然是在观察者的.m文件中实现的,那么该参数则为self)
  • 参数KeyPath:NSString类型,键路径参数,即被观察者的属性参数。(如:被观察者有一个命名为example的属性,而且你要观察的正是这个属性,那就设置这个参数为@"example")

注:如果忘记解除移除监察,会导致资源泄露

  拓展一: KVO手动设置
 KVO模型中,有两种通知观察者的方式,自动通知和手动通知。一般我们都用系统自动通知,文章开篇介绍的就是KVO自动通知。
 KVO手动通知的设置出了完成自动通知的三个步骤,需要在被观察者的.m实现文件中重写类方法:

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
    
}

返回NO时,告诉系统使用KVO手动通知;返回YES时,使用KVO自动通知,默认为YES;
参数key为NSString类型,被监听的keyPath , 用来区分不同的KVO监听。
另外,在当被监听的属性发生变化时,需要调用属性值将要改变的方法和属性值已经改变方法

// 手动通知在需要改变example变量的地方,使用

[self willChangeValueForKey:@"example"];

self.example = @"我是被监听的属性,字符串类型的";

[self didChangeValueForKey:@"example"];


自动通知在需要改变example变量的地方,使用KVC设置属性内容的方法,而不是仅仅使用简单赋值。

[self setValue:@"我是被监听的属性,字符串类型的" forKey:@"example"];

手动改变属性内容时,我们需要在3个地方改变属性的内容值,即:请求结束时、连接出错误,线程被cancel。请在对应的方法代码中加入手动变值的语句。

  拓展二: KVC简单介绍
可以参看这篇文章:iOS开发技巧系列---详解KVC(我告诉你KVC的一切)

参考文章

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

推荐阅读更多精彩内容

  • 上半年有段时间做了一个项目,项目中聊天界面用到了音频播放,涉及到进度条,当时做android时候处理的不太好,由于...
    DaZenD阅读 2,983评论 0 26
  • 本文结构如下: Why? (为什么要用KVO) What? (KVO是什么) How? ( KVO怎么用) Mo...
    等开会阅读 1,613评论 1 21
  • 本篇会对KVO的实现进行探究,不涉及太多KVO的使用方法,但是会有一些使用时的思考。 一、使用上的疑问 1.key...
    奋拓达阅读 478评论 0 2
  • 本文由我们团队的 纠结伦 童鞋撰写。 文章结构如下: Why? (为什么要用KVO) What? (KVO是什么...
    知识小集阅读 7,382评论 7 105
  • 由于明天没有时间,所以提前一天板绘一张圣诞卡,祝大家度过愉快的平安夜后,接着又有一个棒棒的圣诞节!
    TiBi阅读 259评论 2 0