KVO 深入底層探索和遇到的常見錯誤(一)

序言

前幾天公交車上看了一篇百度大神的關于 KVO 探索的博客。我實地驗證了一下子,也遇到了好多問題,一番各種查閱資料之后,決定總結分享一下,供各位看官指點哈~

KVO 的原理

下面的原理仔細品嘗喔~多讀幾遍就可以理解了,當然理解不了就按我說的來點 KVO 的代碼,最后腫能理解
PS:突然發(fā)現(xiàn)簡書的 markdown 語法有點少,比如我想在對下面的 object 加粗時候,就找不到相應的解決方法??
1.當一個 object(對象) 有觀察者時候,動態(tài)創(chuàng)建這個 object(對象) 的類的子類 2.對于每個被觀察的 property(屬性),重寫其 setter 方法 3.在重寫的 setter 方法中調(diào)用 -willChangeValueForKey: 和 -didChangeValueForKey: 通知觀察者 4.當一個 property(屬性) 沒有觀察者時,刪除重寫的方法 5.當沒有 observer(觀察者) 觀察任何一個 property(屬性) 時,刪除動態(tài)創(chuàng)建的子類

Demo 驗證

Demo 簡單到要死,覺著扔一張圖就看的明白,比廢話一大堆簡單多了,有時候看文字是件晦澀的事情,還得一個字一個字的理解,所以此處扔圖??,有想看 Demo 的 點我穿越

Demo

接下來看看 KVO 是怎么動態(tài)創(chuàng)建子類的:
斷點1—>代碼和 Log 日志


斷點1-代碼
斷點1-Log

對比上述2張圖,我們在斷點1處,在控制臺分別使用- classobject_getClass() 打印person對象的類和真實的類,下面的斷點2和斷點3都按此方法打印 Log日志。

斷點2—>代碼和 Log 日志


斷點2-代碼
斷點2-Log

斷點3—>代碼和 Log 日志


斷點3-代碼
斷點3-Log

瞧~,斷點2的 Log 日志信息突然冒出了一個
NSKVONotifying_HQMPerson,這是什么鬼。。。
我們知道為一個對象addObsever時候,也就是被觀察時,
framework使用runtime動態(tài)創(chuàng)建了一個HQMPerson類的子類NSKVONotifying_HQMPerson,而為了不讓外部知道這一行為,
NSKVONotifying_HQMPerson重寫了-class方法返回之前的類,所以通過-class方法查看的類沒有變化,但是通過object_getClass()方式就會暴露出來發(fā)生了何種變化,因為這個object_getClass()返回的是這個對象的isa指針,isa指針指向的一定是這個對象所屬的類。如下圖:

isa 指向 xx

常見錯誤

?.錯誤1-remove觀察者
錯誤1

造成該崩潰信息的代碼片段如下:

崩潰信息的代碼片段

上述代碼是對 person 這個對象添加了監(jiān)聽,而removeObserver方法卻是移除的self,顯然這是一個很低級的錯誤。

解決方法: 觀察誰,誰就應該移除也就是偷窺誰,誰就發(fā)毛,所以就該跑

?.錯誤2-屬性的值修改了的信息收到了,但是并沒有處理

錯誤2

其實這個很簡單就是你addObserver了,
但是方法-observeValueForKeyPath:ofObject:change:context:卻沒有實現(xiàn),這個算是最低級的了??。。。

解決方法:
PS:只要你注冊了 KVO,這個方法就必須實現(xiàn)

?.錯誤3-添加和移除時候,context上下文不一致
錯誤3

代碼片段如下:


context上下文不一致

解決方法:
一般來說context都傳nil

?.錯誤4-致命性
錯誤4

說實話遇到這個錯誤,我還是真不知道從何入手(皆因?qū)?KVO 的理解不夠深),先看出現(xiàn)這種崩潰的原始代碼:

原始代碼片段

只要運行,程序就會爽快的崩潰。。??聪挛业淖⑨專缓笤趯Ρ纫幌卤罎⑷罩拘畔?HQMPerson 類的實例被釋放了,但是 KVO 中還有關于他的注冊信息)。
實際上,只要你明白 KVO 的知識:在添加觀察者的時候,觀察者對象與被觀察的屬性所屬的對象都不會被retain,然而在這些對象被釋放后,相關的監(jiān)聽信息卻還存在,(ARC環(huán)境下)KVO做的處理是直接讓程序崩潰。

解決方法:
既然明白了這一點,我們就知道如何修改了(ARC 環(huán)境下),如下修改:

修改后代碼片段

關于 KVO 的觸發(fā)方式-自動和手動,以及更深的底層探索待續(xù)喔。。。會出 xxx(二) 呢(這部分得參考 apple 的官方文檔,英文有壓力??)

PS:碼一篇文章難,碼一篇好文好好難。馬丹,本來打算每周要寫一篇的甭管是多是少。哦。。。對了,馬丹...是個人名吶??

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,043評論 0 9
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,001評論 25 709
  • 本文代碼下載地址 一:kvo簡介 Objective-C 中的鍵(key)-值(value)觀察(KVO)并不是什...
    雷鳴1010閱讀 461評論 0 0
  • 【下一章】西游殤( 57 )終相見 我剛寫西游殤的時候,寫“神佛無道,欺騙眾生,我要逆天改命!”結果當晚我的電腦硬...
    傅人閱讀 1,123評論 31 26
  • 昨天,終于順利通過了我的研究生畢業(yè)論文答辯,至此,總算可以舒一口氣。 早上八點多從家出發(fā),兒子非哭著追到了公交站,...
    心有歡喜過生活閱讀 587評論 4 4

友情鏈接更多精彩內(nèi)容