你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> KVO底層探索和遇到的常見錯誤(一)

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

編輯:IOS開發基礎

img (186).jpg

投稿文章,作者:keymon

序言

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

KVO的原理

下面的原理仔細品嘗喔~多讀幾遍就可以理解了,當然理解不了就按我說的來點 KVO 的代碼,最後腫能理解

1.當一個 object(對象) 有觀察者時候,動態創建這個 object(對象) 的類的子類

2.對於每個被觀察的 property(屬性),重寫其 setter 方法

3.在重寫的 setter 方法中調用 -willChangeValueForKey: 和 -didChangeValueForKey: 通知觀察者

4.當一個 property(屬性) 沒有觀察者時,刪除重寫的方法

5.當沒有 observer(觀察者) 觀察任何一個 property(屬性) 時,刪除動態創建的子類

Demo 驗證

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

1291197-9c33b5d854af3671.jpg

接下來看看 KVO 是怎麼動態創建子類的:

  • 斷點1—>代碼和 Log 日志

1291197-b9d0b92be40ff49e.jpg

斷點1-代碼

1291197-74280677b1964a18.jpg

斷點1-Log

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

  • 斷點2—>代碼和 Log 日志

1291197-c83709540d7e839a.jpg

斷點2-代碼

1291197-623c99fa548eacc4.jpg

斷點2-Log

  • 斷點3—>代碼和 Log 日志

1291197-5120c041769b1c7e.jpg

斷點3-代碼

1291197-d6e3e2a9eb0fb1ef.jpg

斷點3-Log

瞧~,斷點2的 Log 日志信息突然冒出了一個

NSKVONotifying_HQMPerson,這是什麼鬼。。。

我們知道為一個對象addObsever時候,也就是被觀察時,

framework使用runtime動態創建了一個HQMPerson類的子類NSKVONotifying_HQMPerson,而為了不讓外部知道這一行為,

NSKVONotifying_HQMPerson重寫了-class方法返回之前的類,所以通過-class方法查看的類沒有變化,但是通過object_getClass()方式就會暴露出來發生了何種變化,因為這個object_getClass()返回的是這個對象的isa指針,isa指針指向的一定是這個對象所屬的類。如下圖:

1291197-0b8469b33a3d83ed.jpg

isa 指向 xx

常見錯誤

1.錯誤1-remove觀察者

1467705629131135.jpg

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

1467705649445679.jpg

崩潰信息的代碼片段

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

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

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

1291197-5ee624cd0a543427.jpg

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

解決方法:

PS:只要你注冊了 KVO,這個方法就必須實現

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

1467705733213504.jpg

代碼片段如下:

1467705751946600.jpg

context上下文不一致

解決方法:

一般來說context都傳nil

4.錯誤4-致命性

1291197-dbf5b4a9eeb0f4c1.jpg

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

1467705803538283.jpg

原始代碼片段

只要運行,程序就會爽快的崩潰。。。看下我的注釋,然後在對比一下崩潰日志信息(HQMPerson 類的實例被釋放了,但是 KVO 中還有關於他的注冊信息)。

實際上,只要你明白 KVO 的知識:在添加觀察者的時候,觀察者對象與被觀察的屬性所屬的對象都不會被retain,然而在這些對象被釋放後,相關的監聽信息卻還存在,(ARC環境下)KVO做的處理是直接讓程序崩潰。

解決方法:

既然明白了這一點,我們就知道如何修改了(ARC 環境下),如下修改:

1291197-3667e0c0e0d1dac9.jpg

修改後代碼片段

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

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved