美文网首页kvo
iOS之KVO监听NSMutableArray

iOS之KVO监听NSMutableArray

作者: 无极战思 | 来源:发表于2020-06-25 17:33 被阅读0次

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

    iOS 中 KVO (key-value-observing) 的原理,简单来说就是重写了被观察属性的 set 方法,一般情况下只有通过调用 set 方法对值进行改变才会触发 KVO,直接访问实例变量修改值是不会触发 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(@"改变数据源之后=%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:@"苍白色"]添加对象


    无触发KVO.GIF

    可以看出:是没有触发kvo的代理方法的,array的前后内存地址不变

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


    KVO触发.GIF

    可以看出:触发了kvo的代理方法的,并且array的前后内存地址发生了变化

    为什么会这样:

    NSMutableArray在调用它的 addObject、removeObject 系列方法时,并不会触发它自己的 set 方法。所以,对一个可变数组进行观察,在它加减元素时不会收到期望的消息。
    因为KVO的本质是系统监测到\color{red} {某个属性的内存地址}或常量改变时,会添加上- (void)willChangeValueForKey:(NSString *)key和- (void)didChangeValueForKey:(NSString *)key方法来发送通知,所以一种解决方法是手动调用者两个方法,但是并不推荐,你永远无法像系统一样真正知道这个元素什么时候被改变。另一种便是利用使用mutableArrayValueForKey:了。

    那么为什么mutableArrayValueForKey:这个方法可以监听dataSource内部变化呢?

    mutableArrayValueForKey:默认采用的是搜索模式,在NSMutableArray搜索匹配insertObject:atIndex:和removeObjectAtIndex:等能引起容器内部Object发生改变的方法,如果发现至少一个插入或者删除方法,就会发送发送消息给原始接受者。

    相关文章

      网友评论

        本文标题:iOS之KVO监听NSMutableArray

        本文链接:https://www.haomeiwen.com/subject/xygsfktx.html