iOS原理(二)----KVO,KVC

iOS原理(二)----KVO,KVC

KVO

KVO的全称是Key-Value Observing,俗称“键值监听”,可以用于监听某个对象属性值的改变.下面是一个简单实用KVO的例子:

@interface Animal : NSObject

@property (nonatomic,assign) int age;

@end

@implementation Animal

@end


- (void)viewDidLoad {
    [super viewDidLoad];
    
     self.ani = [[Animal alloc] init];
    self.ani.age = 10;
    [self.ani addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
    

}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    self.ani.age = 20;
}

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

通过断点发现添加KVO后,对象的isa指针变为NSKVONotifying_Animal,

Snip20181109_16.png

setAge实际调用为:NSSetIntValueAndNotify

Snip20181109_17.png

大概实现为:

  • 调用willChangeValueForKey.
  • 调用原来的setter实现.
  • 调用didChangeValueForKey.

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

KVO动态生成的类,还会重写class,dealloc,_isKVOA等.调用class方法,会得到原来的类对象,对外封装实现细节.

所以KVO的本质为:利用RuntimeAPI动态生成一个子类,并且让instance对象的isa指向这个全新的子类,当修改instance对象的属性时,会调用Foundation的_NSSetXXXValueAndNotify函数,然后依次调用willChangeValueForKey,父类原来的setter和didChangeValueForKey(内部会触发监听器(Oberser)的监听方法( observeValueForKeyPath:ofObject:change:context:)).

当对象值没有改变时,我们任然要触发KVO时,我们可以手动触发KVO:手动调用willChangeValueForKey:和didChangeValueForKey.直接修改成员变量的值不会触发KVO.

KVC

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

setValue:forKey:的原理:

  • 按照setKey:、_setKey:顺序查找方法,如果找到方法,传递参数,调用方法.
  • 如果没有找到方法,查看accessInstanceVariablesDirectly方法的返回值.
  • 如果返回值为NO,调用setValue:forUndefinedKey:并抛出异常NSUnknownKeyException.
  • 如果返回值为YES,按照_key、_isKey、key、isKey顺序查找成员变量,如果找到成员变量,就只直接赋值,没有调用setValue:forUndefinedKey:并抛出异常NSUnknownKeyException.

valueForKey:的原理:

  • 按照getKey、key、 isKey、_key顺序查找方法,如果找到方法,调用方法.
  • 如果没有找到方法,查看accessInstanceVariablesDirectly方法的返回值.
  • 如果返回值为NO,调用valueForUndefinedKey:并抛出异常NSUnknownKeyException.
  • 如果返回值为YES,按照_key、_isKey、key、isKey顺序查找成员变量,如果找到成员变量,就只直接赋值,没有调用valueForUndefinedKey:并抛出异常NSUnknownKeyException.

KVC会自动触发KVO.

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • KVC KVC定义 KVC(Key-value coding)键值编码,就是指iOS的开发中,可以允许开发者通过K...
    暮年古稀ZC阅读 2,262评论 2 9
  • 【原创博文,转载请注明出处!】之前做iOS开发的时候经常使用KVO来监听对象属性值的变化去执行一些操作,但是从未思...
    RephontilZhou阅读 1,156评论 1 9
  • KVC(Key-valuecoding)键值编码,单看这个名字可能不太好理解。其实翻译一下就很简单了,就是指iOS...
    榕樹頭阅读 761评论 0 2
  • KVO: KVO的全称是Key-Value Observing,俗称“键值监听”,可以用于监听某个对象属性值的改变...
    曹来东阅读 684评论 0 0
  • 不得不承认的是,企业处理危机公关不仅仅是一门技术,更像是一门艺术。由于处理不当,最终导致企业“轰然倒下”的案例也不...
    5b0eba5323ac阅读 263评论 0 0

友情链接更多精彩内容