iOS的KVO、KVC

turboksiOS192

一: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:



相关文章

暗黑模式适配

暗黑模式适配

先上效果图:正常暗黑一:首先确定自己的主题色比如正常模式下显示紫色、暗黑显示下显示灰色。二:在Assets中新建颜色:创建颜色进行设置:设置颜色左边是正常模式的颜色、右边是暗黑模式下三:举例使用&nb...

GCD定时器

GCD定时器

NSTimer依赖于RunLoop,如果RunLoop的任务过于繁重,可能会导致NSTimer不准时。而GCD的定时器会更加准时。- (void)viewDidLoad {   ...

iOS程序的内存布局

iOS程序的内存布局

    代码段:编译之后的代码    数据段:字符串常量:比如NSString * str = @“123”已初始化数据:已初始化的全局变量...

OC对象的本质

OC对象的本质

我们平时编写的oc代码、底层实现其实是C\C++代码OC代码    ——>    C\C++    ——>  &nbs...

Runtime动态创建类

Runtime动态创建类

- (void)viewDidLoad {    [super viewDidLoad];    Class KSObj = objc_allocateClas...

iOS 之导航渐变,并且跳转返回保持滑动状态

iOS 之导航渐变,并且跳转返回保持滑动状态

导航刚开始进入为透明,根据我们的滑动确定要显示的背景色。先看一下效果图:一:创建demo,将3个界面添加到控制器中,此过程比较简单代码就不上了。二:在第一页的viewDidload中将当前页面的导航设...