KVO 實戰解析

2021-06-19 00:59:25 字數 4892 閱讀 1239

通過乙個遛狗例子來解析kvo  

objective-c 中的鍵(key)-值(value)觀察(kvo)並不是什麼新鮮事物,它**於設計模式中的觀察者模式,其基本思想就是:

乙個目標物件管理所有依賴於它的觀察者物件,並在它自身的狀態改變時主動通知觀察者物件。這個主動通知通常是通過呼叫各觀察者物件所提供的介面方法來實現的。觀察者模式較完美地將目標物件與觀察者物件解耦。

在 objective-c 中有兩種使用鍵值觀察的方式:手動或自動,此外還支援註冊依賴鍵(即乙個鍵依賴於其他鍵,其他鍵的變化也會作用到該鍵)。下面將一一講述這些,並會深入 objective-c 內部一窺鍵值觀察是如何實現的。

1,註冊與解除註冊

如果我們已經有了包含可供鍵值觀察屬性的類,那麼就可以通過在該類的物件(被觀察物件)上呼叫名為 nskeyvalueobserverregistration 的category 方法將觀察者物件與被觀察者物件註冊與解除註冊:

- (void)addobserver:(nsobject *)observer forkeypath:(nsstring *)keypath options:(nskeyvalueobservingoptions)options context:(void *)context;

- (void)removeobserver:(nsobject *)observer forkeypath:(nsstring *)keypath;

這兩個方法的定義在 foundation/nskeyvalueobserving.h 中,nsobject,nsarray,nsset均實現了以上方法,因此我們不僅可以觀察普通物件,還可以觀察陣列或結合類物件。在該標頭檔案中,我們還可以看到 nsobject 還實現了 nskeyvalueobservernotification的 category 方法(更多類似方法,請檢視該標頭檔案):

- (void)willchangevalueforkey:(nsstring *)key;

- (void)didchangevalueforkey:(nsstring *)key;

這兩個方法在手動實現鍵值觀察時會用到,暫且不提。

值得注意的是:不要忘記解除註冊,否則會導致資源洩露。

2,設定屬性

將觀察者與被觀察者註冊好之後,就可以對觀察者物件的屬性進行操作,這些變更操作就會被通知給觀察者物件。注意,只有遵循 kvo 方式來設定屬性,觀察者物件才會獲取通知,也就是說遵循使用屬性的 setter 方法,或通過 key-path 來設定:

[target setage:30]; 

[target setvalue:[nsnumber numberwithint:30] forkey:@"age"];

3,處理變更通知

觀察者需要實現名為 nskeyvalueobserving 的 category 方法來處理收到的變更通知:

- (void)observevalueforkeypath:(nsstring *)keypath ofobject:(id)object change:(nsdictionary *)change context:(void *)context;

在這裡,change 這個字典儲存了變更資訊,具體是哪些資訊取決於註冊時的 nskeyvalueobservingoptions。

我先建立了乙個 dogname 的函式作為被觀察的物件

dogname.h 檔案 **的下劃線/

#import

@inte***ce dogname :nsobject

@property(strong,nonatomic)

nsstring

*dongnamestring;

@end

dogname.m 檔案 **的下劃線/

#import "dogname.h"

@implementationdogname

@synthesize dongnamestring;

-(id)init

returnself;

}

-(void)changename

-(nsstring *)setdogname:(nsstring *)name

//自動通知  大黃走了小花來了一定要告訴主人來 誰在看家

+ (bool) automaticallynotifiesobserversforkey:(nsstring*)key

// 確保呼叫了父類的automaticallynotfiesobserversforkey方法

return

[super

automaticallynotifiesobserversforkey:key];

}

///  在  viewcontroller.h 裡   主人的家//

#import

#import "dogname.h"

@inte***ce viewcontroller :uiviewcontroller

@property(weak,nonatomic)iboutlet

uilabel

*dognamelable;  //在檢視上顯示哪個狗在看家

@end

///  在  viewcontroller.m 裡   //

#import "viewcontroller.h"

#import "dogname.h"

@inte***ce

viewcontroller()

@end

@implementation viewcontroller

@synthesize dognamelable;

- (void)viewdidload

//處理變更通知  狗主人的眼睛 能觀察到是否有其他的狗來**

- (void)observevalueforkeypath:(nsstring *)keypath

ofobject:(id)object

change:(nsdictionary *)change

context:(void *)context

else

}

//搬家了就要       刪除觀察者

-(void)dealloc

- (void)didreceivememorywarning

遛狗的demo:  

實戰解析 開篇

在思想上兜了一圈,我決定要還是落地走走,否則就可能變成一張大嘴而已。接下來要給大家講解的是我的第乙個大專案 x市動力機房監控,在這個專案中我從乙個畢業生成長為單位的開發骨幹。由於不記得當初的技術保密協議到底是 5年還是 10年,所以出於職業精神,我還是不能把所有專案背景和設計進行介紹,抽取我認為沒有...

命令實戰解析

1 split 按照指定的行數或大小分隔檔案 split option input prefix l 指定行數 split l 10 etc inittab new a 指定生成檔案字尾長度 split l 10 a 4 etc inittab new2 d 使用數字字尾 split l 10 d ...

實戰spdk perf解析

spdk的perf能夠充分展現nvme 的高效能,那麼怎麼讓這個利器發揮作用呢?下面分享了100 驗證的完整步驟 並解決編譯依賴 確定代測試盤的 bdv 比如我要測 dev nvme6n1,由於perf需要指定這個裝置對應的pcie的bdf位址,那麼改怎麼確定它呢?root test ls alrt...