IOS KVO原理解析與應(yīng)用

image

IOS KVO原理解析與應(yīng)用

一、KVO概述

KVO,即:Key-Value Observing,是Objective-C對觀察者模式的實現(xiàn),每次當(dāng)被觀察對象的某個屬性值發(fā)生改變時,注冊的觀察者便能獲得通知,這種模式有利于兩個類間的解耦合,尤其是對于業(yè)務(wù)邏輯與視圖控制 這兩個功能的解耦合。

二、KVO有哪些應(yīng)用?

  • NSOperation
  • NSOperationQueue
  • RAC

三、KVO的使用和實現(xiàn)?

1、使用KVO

1.注冊觀察者,指定被觀察對象的屬性:

[_people addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];

2.在觀察者中實現(xiàn)以下回調(diào)方法:

- (void)observeValueForKeyPath:(NSString *)keyPath  
                      ofObject:(id)object  
                        change:(NSDictionary *)change  
                       context:(void *)context  
   
{  
        NSString *name = [object valueForKey:@"name"]; 
        NSLog(@"new name is: %@", name);  
}  

只要People對象中的name屬性發(fā)生變化,系統(tǒng)會自動調(diào)用該方法。

3.最后不要忘了在dealloc中移除觀察者

[_people removeObserver:self forKeyPath:@"age"]; 

2、KVO的實現(xiàn)

KVO 在apple文檔的說明

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指針,重寫了set方法。

讓我們看看代碼

  • 這是我們創(chuàng)建的Myprofile
@interface MyProfile : NSObject
@property (nonatomic,strong) NSString *avatar;
@property (nonatomic,strong) NSString *age;
@property (nonatomic,strong) NSString *name;
@property (nonatomic,strong) NSMutableArray *dataArr;
@property (nonatomic,strong) MyDetail *myDetail;
  • 再看viewcontroller
    self.myprofile = [[MyProfile alloc]init];
    self.myprofile.name = @"sallen";
    NSLog(@"before:%s",object_getClassName(self.myprofile));
    [self.myprofile addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
    self.myprofile.name = @"slim";
    NSLog(@"after:%s",object_getClassName(self.myprofile));

1.通過打印可以看出class明顯發(fā)生了變化,監(jiān)聽之后的class替換了原有classisa指針

image

2.再看看子類

    self.myprofile = [[MyProfile alloc]init];
    self.myprofile.name = @"sallen";
    NSLog(@"before:%@",[self findSubClass:[self.myprofile class]]);
    [self.myprofile addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
    self.myprofile.name = @"slim";
    NSLog(@"after:%@",[self findSubClass:[self.myprofile class]]);

通過打印可以看出明顯多了個子類


image

3.對于容器的監(jiān)聽

 [self.myprofile addObserver:self forKeyPath:@"dataArr" options:NSKeyValueObservingOptionNew context:nil];
 [self.myprofile.dataArr addObject:@"slim"];

通過監(jiān)聽數(shù)組發(fā)現(xiàn),是沒有觸發(fā)的通知的,因為重寫了set方法。
我們可以利用kvc實現(xiàn)對數(shù)組的監(jiān)聽

 [[self.myprofile mutableArrayValueForKeyPath:@"dataArr"] addObject:@"slim"];
image

4.多級路徑屬性

Myprofile類里又包含了MyDetail
Mydetail創(chuàng)建了content屬性
如果我們需要監(jiān)聽myDetail屬性的變化
我們在Myprofile.m通過方法:+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
一個Key觀察多個屬性值的改變。

+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key{
    
    NSSet *keySet = [super keyPathsForValuesAffectingValueForKey:key];
    if ([key isEqualToString:@"myDetail"]) {
        NSSet *set = [NSSet setWithObject:@"_myDetail.content"];
        keySet = [keySet setByAddingObjectsFromSet:set];
    }
    
    return keySet;
}

打印結(jié)果:


image

四、KVO的缺陷

KVO很強大,但是也有缺點
</br>
1.只能重寫 -observeValueForKeyPath:ofObject:change:contex這個方法 來獲得通知,不能使用自定義的selector, 想要傳一個block更是不可能 ,而且還要處理父類的情況 父類同樣觀察一個同樣的屬性的情況 ,但是有時候并不知道父類 是不是對這個消息有興趣。
</br>
2.父類和子類同時存在KVO時,很容易出現(xiàn)對同一個keyPath進行兩次removeObserver操作,從而導(dǎo)致程序crash。要避免這個問題,就需要區(qū)分出KVOself注冊的,還是superClass注冊的,我們可以在 -addObserver:forKeyPath:options:context:-removeObserver:forKeyPath:context這兩個方法中傳入不同的context進行區(qū)分。

五、block方式的實現(xiàn)

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

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

  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時...
    歐辰_OSR閱讀 30,203評論 8 265
  • 該文章屬于劉小壯原創(chuàng),轉(zhuǎn)載請注明:劉小壯[http://www.itdecent.cn/u/2de707c93d...
    劉小壯閱讀 49,044評論 35 227
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,626評論 1 32
  • 描摹圖稿 如果您希望將新的繪制基于現(xiàn)有圖稿,可以描摹此圖稿。例如,通過將圖形引入 Illustrator并描摹它,...
    yingxin閱讀 4,823評論 0 0
  • 人生百態(tài),悲憫天下,含著淚水的微笑,栓釋了不同的人生。逆風(fēng)如解意,容易莫摧殘
    耀府東君閱讀 146評論 0 0

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