學(xué)習(xí)記錄切揭,僅供參考渣淳。歡迎指正!0槁帷入愧!
本質(zhì)是 調(diào)用了 屬性的 setter方法
前提 ? 新建 ?MLPerson類, 設(shè)置 int類型的age屬性
一、 設(shè)置屬性的值 ?添加KVo監(jiān)聽 ?查看監(jiān)聽前后的類對(duì)象的地址值變化
1. 這里使用 runtime 的API ?object_getClass?獲取實(shí)例對(duì)象 的isa指向的類對(duì)象
由此可見棺蛛,person1實(shí)例對(duì)象 設(shè)置KVO監(jiān)聽之后怔蚌,isa指向的類對(duì)象發(fā)生了變化,指向了一個(gè)由runtime動(dòng)態(tài)生成的一個(gè)類 NSKVONotifying_XXX. 且這個(gè)類是 原來類XXX的一個(gè)子類旁赊。
二桦踊、查看添加KVO監(jiān)聽前后 元類對(duì)象的變化
設(shè)置監(jiān)聽前后的 類對(duì)象也發(fā)生了變化
說明:新生成的 子類 NSKVONotifying_XXX 的isa 指向的是 一個(gè)新的元類對(duì)象。
三终畅、查看添加監(jiān)聽前后的方法的具體實(shí)現(xiàn)
設(shè)置監(jiān)聽之前:調(diào)用的是 MLPerson 里邊的 setAge:方法
設(shè)置監(jiān)聽之后:調(diào)用的是新的子類里邊的 setAge:方法籍胯,只不過 里邊調(diào)用了 Foundation框架 里邊的 _NSSetIntValueAndNofify方法
四、窺探?_NSSetIntValueAndNofify 方法實(shí)現(xiàn)
1离福、 當(dāng)監(jiān)聽到 person1 的age屬相值發(fā)生了變化之后杖狼,首先調(diào)用 新生成的子類的 setAge:方法?
? ? ? ? setAge:方法里邊調(diào)用的是 Foundation 框架 的 _NSSetIntValueAndNotify方法
? ? ? ? 右下圖可知
_NSSetIntValueAndNotify的內(nèi)部實(shí)現(xiàn)? ? ? ? ? ??
? ? ? ? ①.先調(diào)用了 willChangeValueForKey:方法
? ? ? ? ②.接著調(diào)用 父類的 setAge:方法(也就是MLPerson里邊的setAge方法,使age的值真正發(fā)生變化)
? ? ? ? ③. 發(fā)生變化之后 會(huì)接著調(diào)用?didChangeValueForKey: 方法
? ? ? ? ? ? 在此方法內(nèi)部妖爷,通知監(jiān)聽器 某個(gè)對(duì)象的 屬性值 發(fā)生了變化 ?接著觸發(fā) KVO的監(jiān)聽方法 ??- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context;
五蝶涩、如果修改了 成員變量會(huì)不會(huì)觸發(fā)KVO?
不會(huì)絮识。因?yàn)闆]有調(diào)用 setter方法
六绿聘、如何手動(dòng)觸發(fā)KVO
手動(dòng)調(diào)用 ?willChangeValueForKey ?和 ?didChangeValueForKey方法