原理:
重写satter方法,通过调用willChangeValueForKey didChangeValueForKey方法通知观察者,被观察的对象发生了改变。
crash场景:
1.KVO 添加次数和移除次数不匹配:
移除了未注册的观察者,导致崩溃。
重复移除多次,移除次数多于添加次数,导致崩溃。
重复添加多次,虽然不会崩溃,但是发生改变时,也同时会被观察多次。
2.添加了观察者,但未实现 observeValueForKeyPath:ofObject:change:context: 方法,导致崩溃。
3.添加或者移除时 keypath == nil,导致崩溃。
crash防护:
通过runtime特性对addObserver:forKeyPath:options:context:、removeObserver:forKeyPath:方法做替换,避免下面几种情况:
添加观察者时:通过关系哈希表判断是否重复添加,只添加一次。
移除观察者时:通过关系哈希表是否已经进行过移除操作,避免多次移除。
观察键值改变时:同样通过关系哈希表判断,将改变操作分发到原有的观察者上。
详细介绍:https://juejin.im/post/6844903927469588488