學(xué)習(xí)記錄,僅供參考。歡迎指正?。?!
本質(zhì)是 調(diào)用了 屬性的 setter方法
前提 ? 新建 ?MLPerson類, 設(shè)置 int類型的age屬性
一、 設(shè)置屬性的值 ?添加KVo監(jiān)聽 ?查看監(jiān)聽前后的類對象的地址值變化
1. 這里使用 runtime 的API ?object_getClass?獲取實例對象 的isa指向的類對象

由此可見,person1實例對象 設(shè)置KVO監(jiān)聽之后,isa指向的類對象發(fā)生了變化,指向了一個由runtime動態(tài)生成的一個類 NSKVONotifying_XXX. 且這個類是 原來類XXX的一個子類。
二、查看添加KVO監(jiān)聽前后 元類對象的變化
設(shè)置監(jiān)聽前后的 類對象也發(fā)生了變化
說明:新生成的 子類 NSKVONotifying_XXX 的isa 指向的是 一個新的元類對象。

三、查看添加監(jiān)聽前后的方法的具體實現(xiàn)
設(shè)置監(jiān)聽之前:調(diào)用的是 MLPerson 里邊的 setAge:方法
設(shè)置監(jiān)聽之后:調(diào)用的是新的子類里邊的 setAge:方法,只不過 里邊調(diào)用了 Foundation框架 里邊的 _NSSetIntValueAndNofify方法

四、窺探?_NSSetIntValueAndNofify 方法實現(xiàn)
1、 當(dāng)監(jiān)聽到 person1 的age屬相值發(fā)生了變化之后,首先調(diào)用 新生成的子類的 setAge:方法?
? ? ? ? setAge:方法里邊調(diào)用的是 Foundation 框架 的 _NSSetIntValueAndNotify方法
? ? ? ? 右下圖可知
_NSSetIntValueAndNotify的內(nèi)部實現(xiàn)? ? ? ? ? ??
? ? ? ? ①.先調(diào)用了 willChangeValueForKey:方法
? ? ? ? ②.接著調(diào)用 父類的 setAge:方法(也就是MLPerson里邊的setAge方法,使age的值真正發(fā)生變化)
? ? ? ? ③. 發(fā)生變化之后 會接著調(diào)用?didChangeValueForKey: 方法
? ? ? ? ? ? 在此方法內(nèi)部,通知監(jiān)聽器 某個對象的 屬性值 發(fā)生了變化 ?接著觸發(fā) KVO的監(jiān)聽方法 ??- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context;

五、如果修改了 成員變量會不會觸發(fā)KVO?
不會。因為沒有調(diào)用 setter方法

六、如何手動觸發(fā)KVO
手動調(diào)用 ?willChangeValueForKey ?和 ?didChangeValueForKey方法
