KVO-理解與簡單使用

来源:http://www.cnblogs.com/BKE6/archive/2017/07/22/7222326.html
-Advertisement-
Play Games

KVO 就是key value observing (鍵值監聽 /觀察者模式)/是一種回調機制 觀察者模式 : 一個目標對象管理所有依賴於他的觀察者對象 /併在它自身的狀態改變時主動通知觀察者對象 /這個制動通知通常是通過調用各觀察者對象所提供的介面方法來實現的 /觀察者模式比較完美的將目標對象和觀 ...


KVO

就是key value observing (鍵值監聽 /觀察者模式)/是一種回調機制

觀察者模式 :

一個目標對象管理所有依賴於他的觀察者對象 /併在它自身的狀態改變時主動通知觀察者對象 /這個制動通知通常是通過調用各觀察者對象所提供的介面方法來實現的 /觀察者模式比較完美的將目標對象和觀察者對象解耦  

簡單來說 : 

在某個對象註冊監聽者後/在被監聽的對象發生改變時/對象會發送一個通知給監聽者/以便監聽者執行回調  就是每次指定的被觀察的對象的屬性被修改後 /KVO就會自動通知響應的觀察者     KVO和KVC一樣都依賴於Runtime的動態及時 /都屬於鍵值編程而且底層實現機制都是isa-swizzling  

KVO運用 : 例-監聽scrollView的contentOffset屬性/來完成用戶滾動時動態改變某些控制項的屬性實現效果(包括漸變導航欄/下拉刷新控制項等效果)

 

KVO使用 : 要求-對象必須能支持KVC機制(NSobject的子類都支持)/(也就是說 賦值通過setter或者KVC)

                 方法-註冊 指定被觀察者的屬性 /實現回調方法 /移除觀察                  適用-很適用模型屬性被修改後 / 引發 UIView的變化 /當更改屬性的值後 /監聽對象會立刻得到通知                  當需要檢測其他類的屬性值變化 /但又不想被觀察的類知道                   有點像FBI監視嫌疑人 /這個時候就可以使用KVO    

蘋果文檔對KVO的實現描述 : 

Automatic key-value observing is implemented using a technique called isa-swizzling... When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class .. 也就是說/他使用的技術是ISA調和技術(isa-swizzling) /在我們對某個對象完成監聽註冊後/編譯器會修改所觀察到的對象的ISA指針 /可能還會修改了被監聽對象的某些屬性 /指向一個中間類而不是真正的類 /從某個意義來看 /這是一場騙局   

系統實現KVO的步驟:

  • 當類A的對象第一次被觀察的時候,系統會在運行期動態創建類A的派生類。我們稱為B(NSKVONotifying_A)。
  • 在派生類B(NSKVONotifying_A)中重寫類A的setter方法,B類在被重寫的setter方法中實現通知機制。
  • 在這個過程中, 被觀察對象的isa指針從指向原來A類的, 被KVO機制修改為指向B(NSKVONotifying_A)類, 來實現當前類屬性值改變的監聽
  • 類B(NSKVONotifying_A)重寫會 class方法,將自己偽裝成類A。類B還會重寫dealloc方法釋放資源。
  • 系統將所有指向類A對象的isa指針指向類B的對象。
  KVC同KVO一樣 /通過isa-swizzling技術實現 /當觀察者被註冊為 一個對象的屬性 的觀察對象 的isa指針被修改(就是當觀察者被註冊為觀察對象 誰的觀察對象?  一個對象的屬性的觀察對象 然後 這個屬性的ISA指針被修改) /指向一個中間類 /而不是真是的類 /其結果是 isa指針的值並不一定能反應實例的實際類 /所以不能依靠isa指針來確定對象是否是一個類的成員 /應該使用class方法來確定對象實例的類  

ISA指針 :

是一個指向Class類指針 /(專業術語是指向元類pointer to the metaclass 用來指向類的類型) /我們可以通過object_getClass方法來獲取這個值 /正常來說 class方法內部的實現就是獲取這個ISA指針代表的元類(metaclass) /但是在kvo機制中 /蘋果註冊監聽對象後 通過object_allocateClassPair動態重新創建了一個新類和元類 /此時object_getClass()獲取的就不是原來ISA指向的元類 /而是新建的元類  ISA指針的作用 :每個對象都有ISA指針 指向該對象的類 /他告訴Runtime系統這個對象的類是什麼 /所以對象註冊為觀察者時 /isa指針指向新類 /那麼這個被觀察者的對象就神奇的變成新子類的對象(或實例)了 /因而在該對象上對setting的調用就會調用已重寫的setter /從而激活鍵值通知機制   

重寫setter方法 :

新類重寫了setter方法解析 :KVO的鍵值觀察通知依賴於NSObject的兩個方法willChangeValueForKey /didChangeValueForKey                                             被觀察屬性發生變化之前 willChangeValueForKey被調用 /通知系統keyPath的屬性值即將改變                                             發生改變後 didChangeValueForKey被調用 /通知系統keyPath的屬性值已經改變                                             之後 - addObserver: forKeyPath: options: context 也會被調用                                              且重寫觀察屬性的setter方法這種繼承方式的註入是在運行時而不是編譯時實現的      

KVO實現步驟


  (options通常傳- NSkeyValueObservingOptionNew|NSkeyValueObservingOptonOld) option是KVO里常見的參數 NSkeyValueObservingOption枚舉: NSkeyValueObservingOptionNew:提供更改前的值 NSkeyValueObservingOptionOld:提供更改後的值 NSkeyValueObservingOptionInitial:觀察最初的值(在註冊觀察服務的時候會調用一次觸發方法) NSkeyValueObservingOptionPrior:分別在值修改前後觸發方法(即一次修改兩次觸發 )   註冊 (哪個要註冊KVO機制 / 觀察的屬性值 / 給你觀察鍵值變化的選擇 /方便傳輸你需要的數據 ) - addObserver: forKeyPath: options: context    實現(回調) (觀察的屬性值/object??? / 存儲了一些變化的數據 比如變化前的數據 變化後的數據 如果註冊時context不為空 這裡就能收到) - observeValueForKeyPath: ofObject: change: context:    移除 增加觀察與取消觀察是成對出現的 所以需要在最後的時候 移除觀察者(可以在- dealloc方法了寫) - removeObserver: forKeyPath:             
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • React在Github上已經有接近70000的 star 數了,是目前最熱門的前端框架。而我學習React也有一段時間了,現在就開始用 React+Redux 進行實戰! 上回說到使用Redux-saga 管理 Redux 應用非同步操作,應用還是只有一個首頁.現在開始構建一個新的投稿頁面並使用 R ...
  • Callbacks 模塊並不是必備的模塊,其作用是管理回調函數,為 Defferred 模塊提供支持,Defferred 模塊又為 Ajax 模塊的 風格提供支持,接下來很快就會分析到 Ajax模塊,在此之前,先看 Callbacks 模塊和 Defferred 模塊的實現。 源碼版本 本文閱讀的源 ...
  • 具體到以編碼方式上傳文件這個問題上.這個問題的完整描述應該是類似於這樣: 網站有自己的登錄認證機制,在不需要在對網站登錄機製做任何修改的前提下,如何自動上傳用戶相關的文件,比如用戶頭像? 我們就以自動上傳用戶頭像為例.我們可以假定已經通過某種方式,得到了用戶頭像的本地路徑.--這個大前提,在基於 ... ...
  • css命名規範 頁面結構命名 導航命名 功能命名 CSS樣式命名 CSS樣式表命名 ...
  • JS中的常用類型轉換(一般用強制轉換):1.強制轉為整數:parseInt;寫法:x = parseInt(x); 2.強制轉換位小為:parseFloat;寫法:x = parseFloat(x); 3.檢測類型:x = parseInt(x); alert(typeof(true)); JS中常 ...
  • HTML5 SQL本地資料庫簡單示例 ...
  • 關鍵詞:屬性、標題、段落、、文本格式化、樣式、鏈接、表格、列表、塊、佈局、表單、框架、背景、實體 ...
  • 新特性概覽 參考文章:http://www.cnblogs.com/Wayou/p/es6_new_features.html 這位前輩寫的很好,建議深入學習 ———————————————————————————————————————————— let命令 let命令用來聲明變數,用法類似於va ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...