iOS 开发之 KVO

1,111 阅读2分钟
原文链接: www.jianshu.com
  • key-value-observing
  • “观察者”设计模式的一种
  • 每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了
  • 使用KVO的要求:对象必须能支持KVC机制——所有NSObject的子类都支持这个机制(iOS之KVC使用

还是拿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


推荐一篇KVO更深层次的讲解:(注意阅读评论,因为isa讲的有些问题,现在不都是喜欢看评论么O(∩_∩)O哈)
iOS开发-KVO的奥秘

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