一莺治、概念定義
由官網(wǎng)文檔可見捂寿,通過對KVC的了解,也是對KVO的進(jìn)一步升華魁瞪。
- KVO 是 Objective-C 對觀察者模式(Observer Pattern)的實現(xiàn)穆律。也是 Cocoa Binding 的基礎(chǔ)。當(dāng)被觀察對象的某個屬性發(fā)生更改時导俘,觀察者對象會獲得通知峦耘。
二、KVO初探
context
系統(tǒng)給的方法:
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
實際運(yùn)用中:
思考:context為什么用NULL類型而不是nil旅薄?
官方文檔說明:
思考:context到底要不要寫成NULL辅髓,有什么影響?設(shè)置它的值到底有什么意義呢少梁?
大致意思:您可以指定NULL并完全依賴鍵路徑字符串來確定更改通知的來源洛口,但是這種方法可能會給對象的父類帶來問題,該對象的超類也出于不同的原因而觀察相同的鍵路徑凯沪。
一種更安全第焰,更可擴(kuò)展的方法是使用上下文確保您收到的通知是發(fā)給觀察者的,而不是超類的妨马。
假如不需要context
此時就需要在
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
這個方法中一層層的去判斷和識別要觀察的對象挺举,流程比較繁瑣
- 由此可得出,對于復(fù)雜的情況烘跺,context的內(nèi)容還是一對一指定性的去設(shè)值湘纵,如果對于多個對象添加觀察都設(shè)置成NULL,則會造成數(shù)據(jù)混亂甚至崩潰液荸。(context相也當(dāng)于tag)
- 好處:context用字符串直接來獲取匹配的方式瞻佛,更加直接,更加容易識別娇钱,更加便利伤柄,更加安全,性能更高
移除通知觀察(需不需要移除)
結(jié)論:如果不移除文搂,則會造成對象地址野指針适刀,所以一定要在跳轉(zhuǎn)頁面的時候移除當(dāng)前頁的KVO
嵌套路徑
自動和手動
核心代碼:
官方解釋:
- 自動
核心代碼
// 自動開關(guān)
+ (BOOL) automaticallyNotifiesObserversForKey:(NSString *)key{
return YES; //啟動自動觀察
}
- 手動
核心代碼
// 自動開關(guān)
+ (BOOL) automaticallyNotifiesObserversForKey:(NSString *)key{
return NO; //關(guān)閉自動觀察,準(zhǔn)備手動觀察
}
可變數(shù)組
-
類似電影或者音樂下載時候的進(jìn)度條煤蹭,多個下載任務(wù)時笔喉,會“實時”的把數(shù)據(jù)結(jié)果反饋給前一頁
核心代碼:
LGPerson.m
LGViewController.m
三取视、KVO實現(xiàn)原理
KVO是基于runtime機(jī)制實現(xiàn)的,KVO運(yùn)用了isa-swizzling技術(shù)常挚,isa-swizzling就是類型混合指針機(jī)制, 將2個對象的isa指針互相調(diào)換, 就是俗稱的黑魔法.
- 當(dāng)某個類的屬性對象第一次被觀察時作谭,系統(tǒng)就會在運(yùn)行期動態(tài)地創(chuàng)建該類的一個派生類,在這個派生類中重寫基類中任何被觀察屬性的setter 方法奄毡。派生類在被重寫的setter方法內(nèi)實現(xiàn)真正的通知機(jī)制折欠。
- 例如如果原類為Person,那么生成的派生類名為NSKVONotifying_Person
- 每個類對象中都有一個isa指針指向當(dāng)前類吼过,當(dāng)一個類對象的第一次被觀察锐秦,那么系統(tǒng)會偷偷將isa指針指向動態(tài)生成的派生類,從而在給被監(jiān)控屬性賦值時執(zhí)行的是派生類的setter方法
- 鍵值觀察通知依賴于NSObject 的兩個方法: willChangeValueForKey: 和 didChangevlueForKey:盗忱;在一個被觀察屬性發(fā)生改變之前酱床, willChangeValueForKey:一定會被調(diào)用,這就 會記錄舊的值趟佃。而當(dāng)改變發(fā)生后扇谣,didChangeValueForKey:會被調(diào)用,繼而 observeValueForKey:ofObject:change:context: 也會被調(diào)用揖闸。