? ? ? ?KVO機(jī)制不像通知機(jī)制那樣通過一個通知中心通知所有觀察者對象,而是在對象屬性變化時通知會被直接發(fā)送給觀察者的對象。圖1為KVO機(jī)制解析圖。
圖1:KVO機(jī)制圖
? ? ? ?可以看到,屬性發(fā)生變化的對象需要發(fā)出消息addObserver:forKeyPath:options:context:給注冊觀察者,使觀察者關(guān)注它的某個屬性的變化。當(dāng)對象屬性變化時,觀察者就會接收到通知,觀察者需要重寫方法observeValueForKeyPath:ofObject:change:context:以響應(yīng)屬性的變化。
? ? ? ?下面我們來看一個實(shí)際的案例,我們使用KVO機(jī)制來監(jiān)視應(yīng)用程序的狀態(tài)變化。應(yīng)用程序委托對象AppDelegate的appStatus屬性是要觀察的屬性。AppDelegate的代碼如下:
? ? ? ?上述代碼中第①行的appStatus屬性是需要觀察的屬性,在Swift版中它的定義上必須要加dynamic,以表示該屬性是在運(yùn)行時動態(tài)派發(fā)的。第②行代碼用于定義觀察者AppStatusObserver,AppStatusObserver是我們的自定義類,它負(fù)責(zé)觀察appStatus屬性的變化。第③行代碼用于創(chuàng)建AppStatusObserver對象。
? ? ? ?第④行代碼是關(guān)鍵,addObserver:forKeyPath:options:context:語句告訴觀察者(AppStatusObserver)開始觀察AppDelegate的appStatus屬性變化,其中參數(shù)addObserver是觀察者對象;forKeyPath是被關(guān)注對象的屬性;options是為屬性變化設(shè)置的選項(xiàng),本例中New和Old表示把屬性新舊兩個值都傳遞給觀察者,這些值是NSKeyValueObservingOptions類型的成員;context參數(shù)是上下文內(nèi)容,它的類型是C語言形式的任何指針類型,
Swift版表示為UnsafeMutablePointer
? ? ? ?觀察者AppStatusObserver的代碼如下:
? ? ? ?因?yàn)镹SObject類實(shí)現(xiàn)了NSKeyValueObserving協(xié)議,所以只需聲明AppStatusObserver繼承了NSObject類,而無需實(shí)現(xiàn)NSKeyValueObserving協(xié)議。
? ? ? ?observeValueForKeyPath:ofObject:change:context: 方法的observeValueForKeyPath 參數(shù)是被關(guān)注的屬性。
? ? ? ?ofObject是被關(guān)注的對象,change是字典類型,包含了屬性變化的內(nèi)容,這些內(nèi)容與注冊時屬性變化設(shè)置的選項(xiàng)(options參數(shù))有關(guān)。context是注冊時傳遞的上下文內(nèi)容。
? ? ? ?第一次運(yùn)行程序到界面時,會有兩個狀態(tài)的變化,日志結(jié)果如下:
? ? ? ?appStatus - launch
? ? ? ?appStatus - active
? ? ? ?如果將應(yīng)用退到后臺,然后再回到前臺,日志結(jié)果如下:
? ? ? ?appStatus - inactive
? ? ? ?appStatus - background
? ? ? ?appStatus - inactive
? ? ? ?appStatus - active
? ? ? ?關(guān)于應(yīng)用程序狀態(tài)變化相關(guān)的內(nèi)容,百恒網(wǎng)絡(luò)在這里就不再解釋了。