美文网首页iOS干货程序员collect
iOS属性改变时如何正确触发KVO/RAC的监听

iOS属性改变时如何正确触发KVO/RAC的监听

作者: 水暮竹妖 | 来源:发表于2017-06-09 02:07 被阅读333次

    现在有一个Person对象

    @interface Person : NSObject
    @property (copy, nonatomic) NSString *name;
    @end
    

    通过KVO或者RAC对其监听后,分别执行下面的代码

    • 外面设置name
        // 1
        _person.name = @"Jack";
        // 2
        [_person setValue:@"Jack" forKey:@"name"];
        // 3
        [_person setValue:@"Jack" forKey:@"_name"];
    
    • 内部设置name
        // 4
        self.name = @"Jack";
        // 5
        _name = @"Jack";
        // 6
        [self setValue:@"Jack" forKey:@"name"];
        // 7
        [self setValue:@"Jack" forKey:@"_name"];
    
    • runtime设置name
        unsigned int outCount = 0;
        Ivar *ivars = class_copyIvarList([Person class], &outCount);
        for (int i = 0; i < outCount; i++) {
            Ivar ivar = ivars[i];
            if ([[NSString stringWithUTF8String:ivar_getName(ivar)] isEqualToString:@"_name"]) {
            // 8
                object_setIvar(_person, ivar, @"Jack");
            }
        }
    

    结果:1、2、4、6会触发监听,而3、5、7、8不会触发。

    原因:KVO的本质是通过isa-swizzling新建了一个子类,并且重写了属性的setter方法,在setter方法的头和尾分别执行了willChangeValueForKey:didChangevlueForKey:两个方法来实现监听的。

    因为1、2、4、6会走setter方法,而3、5、7、8直接设置name属性,并没有走setter方法,所以无法触发监听。

    我们在使用KVC时,key加不加_决定了是否走setter方法。

    RAC的监听机制应该也是和KVO一样,所以如果是使用3的方法设置是不会触发监听的。

    拓展:如何监听数组的变化?

    正常KVO/RAC监听数组时,即使我们修改了数组的内容(这里指修改数组内部的内容-增删改)因为没有触发setter方法所以不会触发监听,最简单的就是加一句self.arr = self.arr就可以触发监听了。

    相关文章

      网友评论

        本文标题:iOS属性改变时如何正确触发KVO/RAC的监听

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