OC--KVO

作者: 啊哈呵 | 来源:发表于2017-09-13 19:41 被阅读15次

    高质量博客
    sunnyxx:《objc kvo简单探索》
    南峰子的技术博客:NSKeyValueObserving(KVO)
    Facebook开源的KVOController
    青少年一定要读的KVO指南

    KVO的原理

    简而言之就是:
    1、当一个object有观察者时,动态创建这个object的类的子类、重写 class隐藏自己,返回原来类的class
    2、对于每个被观察的property,重写其set方法
    3、在重写的set方法中调用- willChangeValueForKey:和- didChangeValueForKey:通知观察者
    4、当一个property没有观察者时,删除重写的方法
    5、当没有observer观察任何一个property时,删除动态创建的子类

    记录一下不常用的用法
    NSKeyValueObservingOptions
    typedef NS_OPTIONS(NSUInteger, NSKeyValueObservingOptions) {
        // 提供属性的新值
        NSKeyValueObservingOptionNew = 0x01,
        // 提供属性的旧值
        NSKeyValueObservingOptionOld = 0x02,
        
        // 如果指定,则在添加观察者的时候立即发送一个通知给观察者
        NSKeyValueObservingOptionInitial NS_ENUM_AVAILABLE(10_5, 2_0) = 0x04,
        
        // 如果指定,则在每次修改属性时,会在修改通知被发送之前预先发送一条通知给观察者
        // 这与-willChangeValueForKey:被触发的时间是相对应的
        NSKeyValueObservingOptionPrior NS_ENUM_AVAILABLE(10_5, 2_0) = 0x08
    };
    

    NSKeyValueObservingOptionInitial

        self.name = @"1";
        NSLog(@"监听前");
        [self addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionInitial |NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];
        NSLog(@"监听后,修改前");
        self.name = @"2";
        NSLog(@"修改后");
        
        /* NSLog
        监听前
        keyPath=name change={
            kind = 1;
            new = 1;
        }
        监听后,修改前
        keyPath=name change={
            kind = 1;
            new = 2;
            old = 1;
        }
        修改后
         */
    

    NSKeyValueObservingOptionPrior

        self.name = @"1";
        
        NSLog(@"监听前");
        [self addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionPrior |NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];
        NSLog(@"监听后,修改前");
        self.name = @"2";
        NSLog(@"修改后");
    
        /* NSLog
        监听前
        监听后,修改前
        keyPath=name change={
            kind = 1;
            notificationIsPrior = 1;
            old = 1;
        }
        keyPath=name change={
            kind = 1;
            new = 2;
            old = 1;
        }
        修改后
         */
    

    依赖设置

    @interface ViewController ()
    @property (nonatomic, strong) NSString *fullName;
    @property (nonatomic, strong) NSString *firstName;
    @property (nonatomic, strong) NSString *lastName;
    @end
    
    @implementation ViewController
    
    // fullName依赖firstName和lastName
    - (NSString *)fullName {
        
        return [NSString stringWithFormat:@"%@ %@",_firstName,_lastName];
    }
    
    + (NSSet *)keyPathsForValuesAffectingFullName {
        
        return [NSSet setWithObjects:@"firstName", @"lastName", nil];
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        [self addObserver:self forKeyPath:@"fullName" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];
        self.firstName = @"lao";
        self.lastName = @"wang";
    
        /*NSLog
         keyPath=fullName change={
         kind = 1;
         new = "lao (null)";
         old = "(null) (null)";
         }
         keyPath=fullName change={
         kind = 1;
         new = "lao wang";
         old = "lao (null)";
         }
         */
    
    }
    

    集合属性 如:NSMutableArray、NSMutableSet、NSMutableOrderedSet

        [self addObserver:self forKeyPath:@"nameArr" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];
        
        self.nameArr = [[NSMutableArray alloc] init]; // 触发KVO
        
        [self.nameArr addObject:@"1"];              // 这么操作不触发KVO
        
        NSMutableArray *arr = [self mutableArrayValueForKey:@"nameArr"];
        // 使用mutableArrayValueForKey获得集合,操纵addObject
        // 下面都触发KVO
        [arr addObject:@"2"];
        [arr replaceObjectAtIndex:0 withObject:@"3"];
        [arr removeAllObjects];
    

    相关文章

      网友评论

          本文标题:OC--KVO

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