ios 中 KVO
KVO(Key value observe)鍵值觀察,是ios中的一種核心的概念,簡單的理解為當某一個對象A(或者多個對象)要想監聽對象的B的一個或者多個屬性發生變化時,就是用這種機制。
? ? ? ? 當某個對象有個屬性改變,KVO會自動的消息通知對方,這樣的架構有多種好處。首先開發人員不需要自己去實現這樣的方案:每次屬性改變了就發送消息通知,這是KVO機制的最大優點,因為這個方案已經被明確定義,獲得框架級的支持,可以方便的采用,開發人員不需要添加任何代碼,不需要設計自己的開發者模型,直接就可以在工程里使用,其次KVO的架構非常強大,可以很容易的支持多個觀察者觀察同一個屬性,以及相關的值? ? ? ? ? ?
? ? ?2、缺點,實時監聽對象屬性值的改變,非常消耗系統的性能。
? ? ?KVO 的面試題。
? ? 1、NSNotification和KVO的區別和用法是什么?什么時候應該使用通知,什么時候應該使用KVO,它們的實現上有什么區別嗎?如果用protocol和delegate(或者delegate的Array)來實現類似的功能可能嗎?如果可能,會有什么潛在的問題?如果不能,為什么?
? ? 答:KVO只能監測屬性的變化,通過NSString類型的屬性名來實現。但是實現了自動監測,當屬性值變化時,會自動通知觀察者,不用再添加代碼了。
? ? ? ? ? NSNotification比較靈活,可以監測的內容較多,但是需要被觀察者手動發送通知,觀察者才能響應。
? ? ? ? ? protocol通過添加一個NSArray也能實現類似的功能,但是實現上需要自己處理delegate的添加與刪除,自己在屬性變化時手動通知,較繁瑣,易出錯
通知機制簡介
/**
?*? NSNotificationCenter 兩個對象之間傳遞消息,或者多個對象之間傳遞消息
?*? a 對象觸發了某個事件(a對象不能完成),需要b對象完成,a對象(void)postNotificationName:(NSString *)aName object:(id)anObject;
?*? postNotificationName 發送消息的名字
?*? object 發送給哪個對象
?*? - (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject; 誰接收通知,接收到通知后實現的方法(SEL)aSelector?
?*? removeObserver移除通知
?*/
? ? 下面的KVO的Demo代碼:
?
1 Person.h內容 2 3 #import <Foundation/Foundation.h> 4 5 @interface Person : NSObject 6 7 @property (nonatomic , copy) NSString *name; 8 @property (nonatomic , assign) int age; 9 10 //- (void)dogNameChange; 11 12 //- (void)dogAgeChange; 13 14 @end 15 16 17 Person.m文件內容 18 #import "Person.h" 19 20 @implementation Person 21 22 //監聽者實現方法 23 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 24 { 25 if ([keyPath isEqual:@"name"]) //dog的name屬性改變了 26 { 27 NSLog(@"Dog - name- change,old:%@ ,new:%@;context = %@",[change objectForKey:NSKeyValueChangeOldKey],[change objectForKey:NSKeyValueChangeNewKey],context); 28 29 } 30 31 if ([keyPath isEqual:@"age"]) //dog的age屬性改變了 32 { 33 NSLog(@"Dog - age - change,old:%@ ,new:%@;context = %@",[change objectForKey:NSKeyValueChangeOldKey],[change objectForKey:NSKeyValueChangeNewKey],context); 34 } 35 } 36 37 //- (NSString *)description 38 //{ 39 // return [NSString stringWithFormat:@"name - %@, age - %d",self.name,self.age]; 40 //} 41 // 42 // 43 //- (void)dogNameChange 44 //{ 45 // NSLog(@"dogNameChange"); 46 //// [self removeObserver:self forKeyPath:@"name"]; 47 //} 48 // 49 //- (void)dogAgeChange 50 //{ 51 // NSLog(@"dogAgeChange"); 52 //} 53 54 @end 55 56 Dog.h內容 57 58 #import <Foundation/Foundation.h> 59 60 @class Person; 61 @interface Dog : NSObject 62 63 64 @property (nonatomic , weak) Person *onwer; 65 @property (nonatomic , assign) NSInteger age; 66 @property (nonatomic , copy) NSString *name; 67 68 @end 69 70 Dog.m內容 71 72 #import "Dog.h" 73 74 @implementation Dog 75 76 77 @end 78 79 ViewController.m內容 80 81 #import "SDViewController.h" 82 #import "Person.h" 83 #import "Dog.h" 84 85 @implementation SDViewController 86 87 - (void)viewDidLoad 88 { 89 [super viewDidLoad]; 90 Person *p = [[Person alloc] init]; 91 p.name = @"張三"; 92 p.age = 18; 93 94 Dog *d = [[Dog alloc] init]; 95 d.age = 10; 96 d.name = @"老狗"; 97 98 //KVO演練 -- 監聽某個對象屬性的改變 99 [d addObserver:p forKeyPath:@"age" options:(0x01 | 0x02) context:@"helloage"]; 100 [d addObserver:p forKeyPath:@"name" options:(0x01 | 0x02) context:@"helloname"]; 101 102 //KVC賦值 103 [d setValue:@(28) forKeyPath:@"age"]; 104 [p setValue:@"李四" forKeyPath:@"name"]; 105 [p setValue:@(10) forKeyPath:@"age"]; 106 [d setValue:@"小狗狗" forKeyPath:@"name"]; 107 108 // [d removeObserver:p forKeyPath:@"name"]; //移除KVO 109 // [d removeObserver:p forKeyPath:@"age"]; //移除KVO 110 111 112 }?
?
?
KVO中的頭文件中重要的方法簡介
/*由于接收器已經被注冊為在相對于物體的關鍵路徑價值的觀察者,被通知更改該值。 變更字典總是包含NSKeyValueChangeKindKey項,其值是一個NSNumber包裝的NSKeyValueChange(使用 - [NSNumber的unsignedIntegerValue])。 NSKeyValueChange的意義取決于什么樣的屬性和關鍵線路識別: - 對于任何類型的屬性(屬性,以一對一的關系,或有序或無序的一對多關系)NSKeyValueChangeSetting表示該觀察對象已經收到了-setValue:forKey:消息,或者說,鍵 - 值編碼兼容的設置方法密鑰已被調用,或者一個-willChangeValueForKey:/ - didChangeValueForKey:對以其他方式被調用。 - 對于_ordered_一對多的關系,NSKeyValueChangeInsertion,NSKeyValueChangeRemoval和NSKeyValueChangeReplacement表明,突變的消息已發送到由-mutableArrayValueForKey返回的數組:發送給對象的消息,或者發送到由-mutableOrderedSetValueForKey返回的有序集合:消息發送給對象,或者說,鍵值中的一個編碼標準的陣列或有序集合突變方法的關鍵已被調用,或者一個-willChange:valuesAtIndexes:forKey:/ - didChange:valuesAtIndexes:forKey:對有否則被調用。 - 對于_unordered_一對多的關系,NSKeyValueChangeInsertion,NSKeyValueChangeRemoval和NSKeyValueChangeReplacement(在Mac OS10.4中引入)表明,突變的消息已發送到由-mutableSetValueForKey返回的集合:發送給對象的消息,或那一個鍵 - 值編碼兼容的一套基因突變的方法對密鑰已被調用,或者一個 -willChangeValueForKey:withSetMutation:usingObjects:/-didChangeValueForKey:withSetMutation:usingObjects:對了,否則被調用。 對于任何形式的財產,變更字典有一個NSKeyValueChangeNewKey項,如果NSKeyValueObservingOptionNew在觀察者注冊時指定,這是正確的一種變化,這是不是事先通知。變更字典包含NSKeyValueChangeOldKey如果指定NSKeyValueObservingOptionOld,這是正確的一種變化。請參閱該NSKeyValueObserverNotification非正式協議的方法是什么這些條目的值可以是評論。 對于一個_ordered_一對多的關系,變更字典總是包含一個NSKeyValueChangeIndexesKey條目的值是包含插入,刪除或替換的對象的索引,除非該變化是NSKeyValueChangeSetting一個NSIndexSet。 如果NSKeyValueObservingOptionPrior(中的Mac OS10.5引入)指定在觀察者登記時間,而該通知是一個先前被發送到的變化,結果,變更字典包含NSKeyValueChangeNotificationIsPriorKey項,其值被一個NSNumber包裝紙是(用 - [NSNumber的boolValue])。 背景始終是在觀察者報名時間的推移,在同一個指針。*///監聽者實現方法 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;//注冊觀察者 -- observer 誰在監聽, keyPath -- 監聽哪一個屬性值 options -- 新的值與舊的值 context -- 傳送給observer 的消息 - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
//移除觀察者 - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(void *)context NS_AVAILABLE(10_7, 5_0); - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
轉載于:https://www.cnblogs.com/ndyBlog/p/3955885.html
總結
- 上一篇: Android工具大杂烩
- 下一篇: 第一阶段冲刺07