iOS开发之KVO

本质(更新于 2019年02月26日23:17:19):

首先,KVO是观察者模式的一种实现
其次,Apple使用了isa(is-a)混写技术,拖runtime的福,在运行时,系统生成了子类NSKVONotifying_SuperClass,然后将isa指针指向子类并重写setter方法,在setter方法上下添加了 willChangeValueForKey 与 didChangeValueForKey方法,所以我们自己也可以手动触发KVO


介绍:

  • key-value-observing
  • “观察者”设计模式的一种
  • 每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了

举例:

还是拿Student类举例(为毛老是拿学生类举例呢,我也是很郁闷呢(⊙﹏⊙))

这个类就一个name属性(只读)
一个giveMeANewName方法,此方法直接操作_name变量

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

#import "Student.h"
@implementation Student
- (NSString*)description {
    NSDictionary* dic = @{
                          @"name":_name == nil ? @"" : _name,
                          };
    return [NSString stringWithFormat:@"%@",dic];
}

- (void)giveMeANewName:(NSString*)name {
    _name = name;
}

@end

在viewContent中:

@interface ViewController ()
@property (nonatomic, strong) Student *stu;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    [self.stu addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
    [self.stu giveMeANewName:@"MT"];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    NSLog(@"%@",change);
}

- (Student*)stu {
    if (!_stu) {
        _stu = [Student new];
    }
    return _stu;
}
@end

运行后发现控制台什么也没有打印,说明这种方式并不能触发KVO


下面进行一些代码修改

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.stu addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
    [self.stu setValue:@"MT" forKey:@"name"];
}

这次用KVC的方式去改变属性值,运行
控制台打印如下信息,这就说明KVC可以触发KVO



如果我们不想用KVC去设置属性值,但又想监听只读属性的变化该怎么处理呢,这里提供一种方式:
在类的扩展中把只读属性改为readwrite

上面代码继续修改:
只读属性name在.m文件中改写为readwrite,giveMeANewName不再直接操作变量而是操作属性(调用set方法)

@interface Student()
@property (nonatomic, copy,readwrite) NSString *name;
@end

- (void)giveMeANewName:(NSString*)name {
    self.name = name;
}

再次运行:
控制台打印如下信息,这就说明这种方式也可以触发KVO


希望会给大家带来帮助(o)/~

你可能感兴趣的:(iOS开发之KVO)