iOS设计模式 —— KV0
刨根问底KVO
KVO 全称 Key-Value Observing。中文叫键值观察。KVO其实是一种观察者模式,观察者在键值改变时会得到通知,利用它可以很容易实现视图组件和数据模型的分离,当数据模型的属性值改变之后作为监听器的视图组件就会被激发,激发时就会回调监听器自身。相比Notification,KVO更加的简单直接。
KVO的操作方法由NSKeyValueCoding提供,而他是NSObject的类别,也就是说ObjC中几乎所有的对象都支持KVO操作。
KVO的使用也很简单,就是简单的3步。
- 注册需要观察的对象的属性addObserver:forKeyPath:options:context:
- 实现observeValueForKeyPath:ofObject:change:context:方法,这个方法当观察的属性变化时会自动调用.在这个方法中还通过NSKeyValueObservingOptionNew这个参数要求把新值在dictionary中传递过来。
- 取消注册观察removeObserver:forKeyPath:context:
我们观察下代码实现,探究实现原理:
Person.h
1 |
#import <Foundation/Foundation.h> @interface Person : NSObject - (void)registerObserver; @property (nonatomic, assign) NSInteger age; @end |
Person.m
1 |
#import "Person.h"
@implementation Person
- (void)registerObserver {
[self addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
|
main函数
1 |
Person * p = [[Person alloc] init]; |
运行程序打印出的log日志为:
1 |
Person,20 |
不要太惊讶,我们慢慢解释。
我重写的Person类的description方法,使用KVC拿到isa指针,获取到self的类名,我们发现在使用KVO之前类名是Person,但注册了KVO之后,类名变成了NSKVONotifying_Person。
主要是因为KVO的实现使用了isa-swizzling。在程序运行时Person会生成一个派生类NSKVONotifying_Person,在这个派生类中重写基类中任何被观察属性的setter方法,用来欺骗系统顶替原先的类。在setter方法中实现真正的通知机制.
1 |
//可以到伪代码 - (void)setAge:(int)age |
我们又可以猜测,使用KVO,内部一定执行setter方法。
当我们把上面代码 p.age = 30;改成p->_age = 30;
你会发现KVO的方法不走了,也证实了这点。
如果p不提供setAge,getAge方法,还想用KVO.
1 |
[p willChangeValueForKey:@"age"]; |
苹果官方KVO文档:
另外.....
我的愿望是.......
世界和平.........
iOS设计模式 —— KV0的更多相关文章
- IOS设计模式之一(MVC模式,单例模式)
iOS 设计模式-你可能已经听说过这个词,但是你真正理解它意味着什么吗?虽然大多数的开发者可能都会认为设计模式是非常重要的,然而关于设计模式这一主题的文章却不多,并且有时候我们开发者在写代码的时候也不 ...
- iOS 设计模式之工厂模式
iOS 设计模式之工厂模式 分类: 设计模式2014-02-10 18:05 11020人阅读 评论(2) 收藏 举报 ios设计模式 工厂模式我的理解是:他就是为了创建对象的 创建对象的时候,我们一 ...
- iOS设计模式之生成器
iOS设计模式之生成器 1.生成器模式的定义 (1): 将一个复杂的对象的构件与它的表示分离,使得相同的构建过程能够创建不同的表示 (2): 生成器模式除了客户之外还包括一个Director(指导者) ...
- IOS设计模式之三:MVC模式
IOS设计模式之三:MVC模式 模型-视图-控制器 这个模式其实应该叫做MCV,用控制器把model与view隔开才对,也就是model与view互相不知道对方的存在,没有任何瓜葛,他们就像一个团 ...
- iOS设计模式 - 享元
iOS设计模式 - 享元 原理图 说明 享元模式使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件:它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件.通常物件中的部分 ...
- iOS设计模式 - 责任链
iOS设计模式 - 责任链 原理图 说明 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链 ...
- iOS设计模式 - 模板
iOS设计模式 - 模板 原理图 说明 定义一个操作中的算法的骨架,而将步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤. 源码 https://github.c ...
- iOS设计模式 - 访问者
iOS设计模式 - 访问者 原理图 说明 表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 1.Visitor 抽象访问者角色,为该对象结构中具 ...
- iOS设计模式 - 迭代器
iOS设计模式 - 迭代器 原理图 说明 提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示. 源码 https://github.com/YouXianMing/iOS-Des ...
随机推荐
- [OpenCV]DMatch类和KeyPoints类:特征点匹配
DMatch struct CV_EXPORTS_W_SIMPLE DMatch { CV_WRAP DMatch() : queryIdx(-), trainIdx(-), imgIdx(-), d ...
- 寻找完全数(C++)
[问题描述] 输入一个大于 1 的正整数 n,请你将大于 1 和小于或等于 n 的所有完全数输出.所谓完全数就是因子(不算其本身)之和等于它本身的数.例如 1+2+4+7+14=28,所以 28 是完 ...
- node gyp的问题
解决 binding.gyp not found (xxx/xxx/xxx) while trying to load binding.gyp 问题 在使用ccap图形验证码模块时遇到这个问题 Err ...
- ThinkPHP自定义成功界面、失败界面、异常界面
在ThinkPHP的手册中,附录里边的配置参考,有一个模板引擎设置. 或者在手册里面的控制器,跳转和重定向里面. 紧接着,就讲到了如何自定义这些界面. 将上诉的配置参数写到到配置文件里,修改路径到自己 ...
- URAL 1741 Communication Fiend(最短路径)
Description Kolya has returned from a summer camp and now he's a real communication fiend. He spends ...
- HDU 2139 Calculate the formula
http://acm.hdu.edu.cn/showproblem.php?pid=2139 Problem Description You just need to calculate the su ...
- 详细介绍javascript中的几种for循环的区别
偶然间见到了forEach循环,感觉很新奇,就研究了一下,顺带着把js中的几种for循环做了一个比较. 首先,简单说一下,js中一共大概有四种for循环:(1).那种简单常见的for循环:(2).fo ...
- Eclipse打不开,闪退
自己编写了个程序,运行巨慢..无语,输出太多,后来冒出一个错误,不知什么原因啊,再后来Eclipse就打不开了,到workbench闪退... 百度后解决方案: 进入目录:workspace/.met ...
- [Leetcode] climbing stairs 爬楼梯
You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...
- 【BZOJ 4007】[JLOI2015]战争调度 DP+搜索+状压
又是一道思路清新的小清晰. 观察题目,如果我们确定了平民或者贵族的任意一方,我们便可以贪心的求出另一方,至此20分:我们发现层数十分小,那么我们就也是状压层数,用lca转移,线性dp,至此50分(好像 ...