iOS的KVO、KVC

turboksiOS290

一:KVO

  在实际的开发过程中,我们可能会遇到这种需求,就是需要根据一个对象某个属性值的改变,来作出不同的处理。但是实现起来比较麻烦,需要在很多地方进行判断处理,为了方便我们的开发,苹果推出了一个专门处理这种问题的解决方案,叫做KVO,负责监听属性值的改变、当发生改变的时候,可以及时的通知我们。

KVO的全程是Key-Value Observing,俗称“键值监听”,可以用于监听某个对象属性值的改变。

先来一个例子,下边在开始讲解原理。

KSPerson.h 文件

@interface KSPerson : NSObject

@property (nonatomic, strong) NSString * name;

@end

ViewController中:

#import "ViewController.h"

#import "KSPerson.h"

@interface ViewController ()

@property (nonatomic, strong) KSPerson * ks;

@end

@implementation ViewController

- (void)viewDidLoad {

    [super viewDidLoad];


    _ks= [[KSPersonalloc]init];

    _ks.name=@"Rose";

    [_ks addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];

}

- (void)touchesBegan:(NSSet *)toucheswithEvent:(UIEvent*)event{

    _ks.name=@"Jack";

}

- (void)observeValueForKeyPath:(NSString*)keyPathofObject:(id)objectchange:(NSDictionary *)changecontext:(void*)context{

    NSLog(@"%@",change);

}

@end

当我们点击屏幕的时候,会触发observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context 方法。

原理:

我们使用xocde添加断点,打印类名:



kvo

根据打印的数据可以看出,添加KVO监听的对象的class类型变成了NSKVONotifying_KSPerson,不是我们想象中的KSPerson了。

这是因为利用RuntimeAPI动态生成一个子类,并且让instance对象的isa指向这个全新的子类

当修改instance对象的属性时,会调用Foundation的_NSSetXXXValueAndNotify函数

willChangeValueForKey:

父类原来的setter

didChangeValueForKey:

内部会触发监听器(Oberser)的监听方法( observeValueForKeyPath:ofObject:change:context:)

当调用set方法的时候,NSKVONotifying_KSPerson会先调用自己的Foundation  _NSSetXXXValueAndNotifiy方法,查看_NSSet* AndNotify的存在:



借图

_NSSet*ValueAndNotify的内部实现:

    [self willChangeValueForKey:@"name"];

    //原来的setter实现

    [self didChangeValueForKey:@"name"];

调用willChangeValueForKey:

调用原来的setter实现

调用didChangeValueForKey:

didChangeValueForKey:内部会调用observer的observeValueForKeyPath:ofObject:change:context:方法


二:KVC

KVC的全称是Key-Value Coding,俗称“键值编码”,可以通过一个key来访问某个属性。

常见的API如下:

- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;

- (void)setValue:(id)value forKey:(NSString *)key;

- (id)valueForKeyPath:(NSString *)keyPath;

- (id)valueForKey:(NSString*)key; 




setvalue:forkey:



valueforkey:



相关文章

iOS的分类(Category)

iOS的分类(Category)

一:Category的底层结构定义在objc-runtime-new.h中:struct category_t {    const char *name;   ...

百度地图自定义marker

百度地图自定义marker

#import "HomeViewController.h"#import "PaopaoView.h"@interface HomeViewControlle...

iOS多线程

iOS多线程

多线程常见方案一、GCD的函数:GCD中有2个用来执行任务的函数queue:队列block:任务1.    用同步的方式执行任务dispatch_sync(di...

isKindOfClass和isMemberOfClass的区别

isKindOfClass和isMemberOfClass的区别

+ (BOOL)isMemberOfClass:(Class)cls {//    类的元类 与 传入类 对比    return object_getClas...

OC的实例对象、类对象、元类对象的关系

OC的实例对象、类对象、元类对象的关系

Objective-C中的对象、简称OC对象,主要分为三种:instance对象(实例对象)、class对象(类对象)、meta-class对象(元类对象)。一:instance对象instance对...

Runtime详解

Runtime详解

The Objective-C language defers as many decisions as it can from compile time and link time to runti...