美文网首页
KVO 相关

KVO 相关

作者: user_bo | 来源:发表于2018-12-03 09:52 被阅读0次
    • 1 . KVO 的基本使用
      kvo "键值监听", 全称"Key-Value Observing" ,监听对象属性值的改变
    // 监听对象
    @interface Person : NSObject
    // 监听属性
    @property (nonatomic,copy)NSString * name;
    @end
    
    @implementation Person
    @end
    
    //----------------------------
    
    @interface ViewController : UIViewController
    @end
    
    @interface ViewController ()
    
    // 创建对象
    @property (nonatomic,strong)Person *person;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        self.person = [Person new];
        self.person.name = @"jack";
        
    // 配置监听
        NSKeyValueObservingOptions options = NSKeyValueObservingOptionOld |NSKeyValueObservingOptionNew;
        [self.person addObserver:self forKeyPath:@"name" options:options context:nil];
    }
      // 触发监听
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
        self.person.name = @"rose";
    }
    
    // 监听调用
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
        NSLog(@"keyPaht ::%@ ; object ::%@  ; change ::%@ ;context ::%@ ",keyPath,object,change,context);
    }
    
    // 移除监听
    - (void)dealloc
    {
        [self.person removeObserver:self forKeyPath:@"name"];
    }
    @end
    
    /*
    keyPaht ::name ; 
    object ::<Person: 0x600003bfc340>  ; 
    change ::{
        kind = 1;
        new = rose;
        old = jack;
    } ;
    context :: (null)
    */
    
    
    • 2 . kvo 的本质
      a. 属性值的改变,其本质是调用内部的set 方法;
      b. 利用runtime,动态生成了 NSKVONotifying_Person 类 继承于 Person类(NSKVONotifying_Person superclass 指向 person),
      同时修改person 对象的isa 指向了 NSKVONotifying_Person 类 复写set 方法,class 方法
      (NSKVONotifying_Person 有自己的元类对象 ,所以 类对象的isa 指向自己的元类对象)
      c. 在set 方法中调用 willchange 等方法;

    @interface NSKVONotifying_Person : Person
    @end
    /*新增
    _isKVOA
    dealloc
    class // return 【Person class】
    setName //调用Foundation 下的 _NSSetXXXValueAndNotify(c 函数)
    */

    伪代码
    @implementation NSKVONotifying_Person
    -(void)setName(NSString *)name{
    _NSSetXXXValueAndNotify()
    }
    void _NSSetIntValueAndNotify() {
    [self willChangeValueForKey:@"name"];
    [super setName:@"xx"];// 调用父类(person 类修改person 的值)
    [self didChangeValueForKey:@"name"];
    }
    -(void)didChangeValueForKey(NSString *)name{
    【observer observeValueForKeyPath... 】
    }
    @end

    • 3 .手动触发 kvo
    // 手动调用 
    
    - (void)willChangeValueForKey:(NSString *)key;
    - (void)didChangeValueForKey:(NSString *)key;
    
    //因为在 didChange方... 法中判断 willChange... 是否有调用 ,所以要先调用willChange...
    
    
    • 4 . 触发kvo的前提:对象的属性 必须有 set 方法;
    @interface Person : NSObject{
        int age;
    }
    @property (nonatomic,copy)NSString * name;
    @end
    
     // -----------------
    
    @interface ViewController ()
    
    @property (nonatomic,strong)Person *person;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        self.person = [Person new];
        self.person.name = @"jack";
        self.person->age = 12;
       
        NSKeyValueObservingOptions options = NSKeyValueObservingOptionOld |NSKeyValueObservingOptionNew;
        [self.person addObserver:self forKeyPath:@"name" options:options context:nil];
        [self.person addObserver:self forKeyPath:@"age" options:options context:nil];
    }
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        self.person.name = @"rose";
        self.person->age = 13;
    }
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
       
        NSLog(@"keyPaht ::%@ ; object ::%@  ; change ::%@ ;context ;;%@ ",keyPath,object,change,context);
    }
    
    - (void)dealloc
    {
        [self.person removeObserver:self forKeyPath:@"name"];
    }
    
    /*
    这里只能监听到name属性 ; 无法监听 age 属性;
    因为age 并没有set 方法,所以不会触发监听;
    */ 
    @end
    
    
    • 5 . 属性和成员变量得区别
      可以参照这篇博客

    https://www.cnblogs.com/huangzs/p/7508583.html

    相关文章

      网友评论

          本文标题:KVO 相关

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