说到KVC
不得不说Set
和Get
正常访问属性都是用Set
方法和Get
方法
但是苹果还提供了另外一种方法就是KVC
全称Key-Value Coding
中文就是键值编码
简单点来说就是直接
用valueForKey
和valueForKeyPath
来获取属性的值
用setValue forKey
和setValue forKeyPath
来修改属性的值
相当于间接访问属性
这样的好处是可以访问私有属性
还有就是字典转模型
调用Set
方法时
1 | - (void)setValue:(id)value forKey:(NSString *)key; |
程序会先查找SetKey
_SetKey
如果没有找到SetKey
_SetKey
就会走+(BOOL)accessInstanceVariablesDirectly
这个方法
这个方法是能不能访问成员变量
默认都是YES
当自己的私有变量不想让外部访问的时候可以重写这个方法返回NO
如果返回NO
的话就会报错
1 | - (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key |
返回 YES 的话
就会去遍历_key
、_isKey
、key
、isKey
还没有的话就会报错
1 | - (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key |
调用Get
方法时
1 | - (nullable id)valueForKey:(NSString *)key; |
程序会先查找getKey
Key
isKey
_Key
如果没有找到getKey
Key
isKey
_Key
就会走+(BOOL)accessInstanceVariablesDirectly
这个方法
这个方法是能不能访问成员变量
默认都是YES
当自己的私有变量不想让外部访问的时候可以重写这个方法返回NO
如果返回NO
的话就会报错
1 | - (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key |
返回 YES 的话
就会去遍历_key
、_isKey
、key
、isKey
还没有的话就会报错
1 | - (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key |
KVO的依赖于OC的Runtime来实现的,当观察者对象时,KVO机制动态创建一个对象A的子类(NSKVONotifying_A类),并为这个子类重写了被观察的属性的setter方法,setter方法会负责调用原来的setter方法前后,通知观察对象发生了变化
1 | //直接通过Key来取值 |
KVC
全称Key Value Observing
中文就是键值观察
听名字就能猜个大概
观察说明当值改变的时候就会告诉你
首先要注册观察者addObserver:forKeyPath:options:context:
然后实现observeValueForKeyPath:ofObject:change:context
最后需要移出观察removeObserver:forKeyPath
KVC
原理
注册KVC
之后
会生成一个NSKVONotifying_
的类
该类继承于观察对象并将原来的对象的isa
指向这个新类
并重写了class
方法返回原类的名字
还有就是重写了Set
方法
这样当调用Set
方法的时候
这个新类就会知道
修改值之前会调用willChangeValueForKey:
方法
修改值之后会调用didChangeValueForKey:
方法
这两个方法最终都会被调用到observeValueForKeyPath:ofObject:change:context:
里面
KVO和通知的区别
相同点:都是对象之间传递信息的一种机制,都需要注册移除
不同点:
KVO 是一对一,只支持属性的更改,只是用了Runtime
动态创建一个心类,重写Set
方法并通过协议的方法回调
通知是一对多,通知支持的类型更广,相当于广播,但是名字不能重复