• OC——关于KVO


    我们知道在WPF、Silverlight中都有一种双向绑定机制,如果数据模型修改了之后会立即反映到UI视图上,类似的还有如今比较流行的基于MVVM设计模式的前端框架,例如Knockout.js。其实在ObjC中原生就支持这种机制,它叫做Key Value Observing(简称KVO)。KVO其实是一种观察者模式,利用它可以很容易实现视图组件和数据模型的分离,当数据模型的属性值改变之后作为监听器的视图组件就会被激发,激发时就会回调监听器自身。在ObjC中要实现KVO则必须实现NSKeyValueObServing协议,不过幸运的是NSObject已经实现了该协议,因此几乎所有的ObjC对象都可以使用KVO。

    在ObjC中使用KVO操作常用的方法如下:

    • 注册指定Key路径的监听器: addObserver: forKeyPath: options:  context:
    • 删除指定Key路径的监听器: removeObserver: forKeyPathremoveObserver: forKeyPath: context:
    • 回调监听: observeValueForKeyPath: ofObject: change: context:

    如何使用KVO呢?

    首先,你要为你想观察的对象添加一个观察者代码如下:

    [object addObserver: observer forKeyPath: @"frame" options: 0 context: nil];

    调用方法是:

    object : 被观察对象

    observer: 观察对象

    forKeyPath里面带上property的name,如UIView的frame、center等等

    options: 有4个值,分别是:

    NSKeyValueObservingOptionNew 把更改之后的值提供给处理方法

    NSKeyValueObservingOptionOld 把更改之前的值提供给处理方法

    NSKeyValueObservingOptionInitial 把初始化的值提供给处理方法,一旦注册,立马就会调用一次。通常它会带有新值,而不会带有旧值。

    NSKeyValueObservingOptionPrior 分2次调用。在值改变之前和值改变之后。

    注:例子里的0就代表不带任何参数进去

    context: 可以带入一些参数,任何类型都可以,强制转就可以。

    接下来观察到值的变化后该应该调用相关的方法来处理,这个方法是:

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

    其中:

    keyPath: 对应forKeyPath

      object:  被观察的对象

      change:  对应options里的NSKeyValueObservingOptionNew、NSKeyValueObservingOptionOld等

      context: 对应context

    示例代码

    头文件

     1 #import <Foundation/Foundation.h>
     2 
     3 @interface Student : NSObject
     4 @property (nonatomic)NSString *name;
     5 
     6 @property (nonatomic)NSString *courseName;
     7 
     8 @property (nonatomic)double age;
     9 
    10 - (void)changeCourseName:(NSString *)newCourseName;
    11 @end

    实现文件

     1 #import "Student.h"
     2 
     3 @implementation Student
     4 
     5 - (id)init
     6 {
     7     if(self = [super init])
     8     {
     9         
    10         [self addObserver:self
    11               forKeyPath:@"courseName"
    12               options:NSKeyValueObservingOptionNew
    13          |NSKeyValueObservingOptionOld
    14                 context:nil];
    15         [self addObserver:self
    16               forKeyPath:@"age"
    17                  options:NSKeyValueObservingOptionNew
    18          |NSKeyValueObservingOptionOld
    19                  context:nil];
    20     }
    21     return self;
    22 }
    23 
    24 - (void)changeCourseName:(NSString *)newCourseName{
    25     
    26     _courseName = newCourseName;
    27      
    28 }
    29 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    30 {
    31     if([keyPath isEqualToString:@"courseName"])
    32     {
    33         NSLog(@"课程发生了改变");
    34         NSLog(@"新课程是:%@  老课程是:%@",[change objectForKey:@"new"],[change objectForKey:@"old"]);
    35 
    36     }
    37     else if([keyPath isEqualToString:@"age"])
    38     {
    39         NSLog(@"年龄发生了改变");
    40         NSLog(@"新年龄是:%@  老年龄是:%@",[change objectForKey:@"new"],[change objectForKey:@"old"]);
    41     }
    42 }
    43 #pragma mark 重写销毁方法
    44 -(void)dealloc//注意一定要移除监听
    45 {
    46     //[super dealloc];//注意启用了ARC,此处不需要调用
    47     [self removeObserver:self forKeyPath:@"courseName"];
    48     [self removeObserver:self forKeyPath:@"age"];
    49 
    50 }
    51 @end

    调用函数

    #import <Foundation/Foundation.h>
    #import "Student.h"
    #import "pageView.h"
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            Student *student = [[Student alloc] init];
            student.courseName = @"math";
            student.age = 10;
            student.courseName = @"ddd";
            student.age = 15;
            
        }
        return 0;
    }

    输出结果

    2015-07-10 14:59:13.074 TestKVO[1649:1396305] 课程发生了改变

    2015-07-10 14:59:13.076 TestKVO[1649:1396305] 新课程是:math  老课程是:<null>

    2015-07-10 14:59:13.076 TestKVO[1649:1396305] 年龄发生了改变

    2015-07-10 14:59:13.076 TestKVO[1649:1396305] 新年龄是:10  老年龄是:0

    2015-07-10 14:59:13.076 TestKVO[1649:1396305] 课程发生了改变

    2015-07-10 14:59:13.076 TestKVO[1649:1396305] 新课程是:ddd  老课程是:math

    2015-07-10 14:59:13.077 TestKVO[1649:1396305] 年龄发生了改变

    2015-07-10 14:59:13.077 TestKVO[1649:1396305] 新年龄是:15  老年龄是:10

     

  • 相关阅读:
    django--orm操作
    路由
    django ----视图和路由
    DJango 前三天小结
    JQuery----操作01
    前端---JQuery初识
    前端----jsDOM
    前端---js02
    前端-----js
    面向对象
  • 原文地址:https://www.cnblogs.com/zhangjingyangjinjin/p/4635768.html
Copyright © 2020-2023  润新知