KVO机制不像通知机制那样通过一个通知中心通知所有观察者对象,而是在对象属性变化时通知会被直接发送给观察者的对象。图1为KVO机制解析图。
图1:KVO机制图
可以看到,属性发生变化的对象需要发出消息addObserver:forKeyPath:options:context:给注册观察者,使观察者关注它的某个属性的变化。当对象属性变化时,观察者就会接收到通知,观察者需要重写方法observeValueForKeyPath:ofObject:change:context:以响应属性的变化。
下面我们来看一个实际的案例,我们使用KVO机制来监视应用程序的状态变化。应用程序委托对象AppDelegate的appStatus属性是要观察的属性。AppDelegate的代码如下:
上述代码中第①行的appStatus属性是需要观察的属性,在Swift版中它的定义上必须要加dynamic,以表示该属性是在运行时动态派发的。第②行代码用于定义观察者AppStatusObserver,AppStatusObserver是我们的自定义类,它负责观察appStatus属性的变化。第③行代码用于创建AppStatusObserver对象。
第④行代码是关键,addObserver:forKeyPath:options:context:语句告诉观察者(AppStatusObserver)开始观察AppDelegate的appStatus属性变化,其中参数addObserver是观察者对象;forKeyPath是被关注对象的属性;options是为属性变化设置的选项,本例中New和Old表示把属性新旧两个值都传递给观察者,这些值是NSKeyValueObservingOptions类型的成员;context参数是上下文内容,它的类型是C语言形式的任何指针类型,
Swift版表示为UnsafeMutablePointer
观察者AppStatusObserver的代码如下:
因为NSObject类实现了NSKeyValueObserving协议,所以只需声明AppStatusObserver继承了NSObject类,而无需实现NSKeyValueObserving协议。
observeValueForKeyPath:ofObject:change:context: 方法的observeValueForKeyPath 参数是被关注的属性。
ofObject是被关注的对象,change是字典类型,包含了属性变化的内容,这些内容与注册时属性变化设置的选项(options参数)有关。context是注册时传递的上下文内容。
第一次运行程序到界面时,会有两个状态的变化,日志结果如下:
appStatus - launch
appStatus - active
如果将应用退到后台,然后再回到前台,日志结果如下:
appStatus - inactive
appStatus - background
appStatus - inactive
appStatus - active
关于应用程序状态变化相关的内容,百恒网络在这里就不再解释了。