kvo的底层实现

KVO的底层实现

KVO是objective-C对观察者模式的实现,也是Cocoa Binding 的基础.当被观察对象的某个属性发生更改时,观察者会获得通知.

不需要给被观察的对象添加任何额外代码,就能使用KVO.

KVO 实现机制

KVO的实现依赖于OC强大的Runtime.
官方文档:

Key-Value Observing Implementation Details 

Automatic key-value observing is implemented using a technique called isa-swizzling. 

The isa pointer, as the name suggests, points to the object's class which maintains a dispatch table. This dispatch table essentially contains pointers to the methods the class implements, among other data. 

When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class. As a result the value of the isa pointer does not necessarily reflect the actual class of the instance. 

You should never rely on the isa pointer to determine class membership. Instead, you should use the class method to determine the class of an object instance.

被观察者对象的isa 指针会指向一个中间类,而不是原来真正的类.
简单概述KVO的实现:

当你观察一个对象时,一个新的类会动态被创建.这个类继承自该对象的原本的类,并重写了被观察者属性的setter方法.自然,重写的setter方法会负责在调用原setter方法之前和之后,通知所有观察对象值的更改.最后把这个对象的isa指针(isa 指针告诉Runtime系统这个对象的类)指向这个新创建的子类,对象就神奇的变成了新创建的子类的实例.

这个中间类,继承自原本的那个类,不仅如此,apple还重写了-class方法,企图欺骗我们这个类没有变,就是原本那个类.

KVO的缺陷

KVO 很强大,没错。知道它内部实现,或许能帮助更好地使用它,或在它出错时更方便调试。但官方实现的 KVO 提供的 API 实在不怎么样。

比如,你只能通过重写 -observeValueForKeyPath:ofObject:change:context: 方法来获得通知。想要提供自定义的 selector ,不行;想要传一个 block ,门都没有。而且你还要处理父类的情况 - 父类同样监听同一个对象的同一个属性。但有时候,你不知道父类是不是对这个消息有兴趣。虽然 context 这个参数就是干这个的,也可以解决这个问题 - 在 -addObserver:forKeyPath:options:context: 传进去一个父类不知道的 context。但总觉得框在这个 API 的设计下,代码写的很别扭。至少至少,也应该支持 block 吧。

有不少人都觉得官方 KVO 不好使的。Mike Ash 的 Key-Value Observing Done Right,以及获得不少分享讨论的 KVO Considered Harmful 都把 KVO 拿出来吊打了一番。所以在实际开发中 KVO 使用的情景并不多,更多时候还是用 Delegate 或 NotificationCenter。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值