iOS之KVO監(jiān)聽NSMutableArray

Demo地址: https://github.com/hanhuitao/KVO-NSMutableArray.git

iOS 中 KVO (key-value-observing) 的原理,簡單來說就是重寫了被觀察屬性的 set 方法,一般情況下只有通過調(diào)用 set 方法對值進(jìn)行改變才會觸發(fā) KVO,直接訪問實例變量修改值是不會觸發(fā) KVO 的。

先上代碼

    #import "ViewController.h"
    @interface ViewController ()
    @property(nonatomic, strong)NSMutableArray * array;
    @end

    @implementation ViewController
    -(NSMutableArray*)array
    {
        if (!_array) {
            _array=[NSMutableArray new];
        }
        return _array;
    }
    - (void)viewDidLoad {
        [super viewDidLoad];
        [self.array addObjectsFromArray:@[@"黑色",@"白色"]];
        NSLog(@"初始化地址=%p",self.array);
        [self addObserver:self forKeyPath:@"array" options:NSKeyValueObservingOptionNew context:nil];

        
        
    }

    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
    //    [self.array addObject:@"蒼白色"];
     //   [[self mutableArrayValueForKey:@"array"]addObject:@"蒼白色"];
        NSLog(@"改變數(shù)據(jù)源之后=%p",self.array);

    }


    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
    {
       
    NSLog(@"keyPath=%@,object=%@,change=%@,context=%@",keyPath,object,change,context);
        
        

    }

@end

我們注意看touchesBegan里面的兩行代碼
1.使用[self.array addObject:@"蒼白色"]添加對象


無觸發(fā)KVO.GIF

可以看出:是沒有觸發(fā)kvo的代理方法的,array的前后內(nèi)存地址不變

2.使用 [[self mutableArrayValueForKey:@"array"]addObject:@"蒼白色"]添加對象


KVO觸發(fā).GIF

可以看出:觸發(fā)了kvo的代理方法的,并且array的前后內(nèi)存地址發(fā)生了變化

為什么會這樣:

NSMutableArray在調(diào)用它的 addObject、removeObject 系列方法時,并不會觸發(fā)它自己的 set 方法。所以,對一個可變數(shù)組進(jìn)行觀察,在它加減元素時不會收到期望的消息。
因為KVO的本質(zhì)是系統(tǒng)監(jiān)測到\color{red} {某個屬性的內(nèi)存地址}或常量改變時,會添加上- (void)willChangeValueForKey:(NSString *)key和- (void)didChangeValueForKey:(NSString *)key方法來發(fā)送通知,所以一種解決方法是手動調(diào)用者兩個方法,但是并不推薦,你永遠(yuǎn)無法像系統(tǒng)一樣真正知道這個元素什么時候被改變。另一種便是利用使用mutableArrayValueForKey:了。

那么為什么mutableArrayValueForKey:這個方法可以監(jiān)聽dataSource內(nèi)部變化呢?

mutableArrayValueForKey:默認(rèn)采用的是搜索模式,在NSMutableArray搜索匹配insertObject:atIndex:和removeObjectAtIndex:等能引起容器內(nèi)部Object發(fā)生改變的方法,如果發(fā)現(xiàn)至少一個插入或者刪除方法,就會發(fā)送發(fā)送消息給原始接受者。

最后編輯于
?著作權(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ù)。

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