KVO

作者: 牛奶红茶 | 来源:发表于2021-02-26 10:13 被阅读0次

1.iOS用什么方式实现对一个个对象的KVO?(KVO的本质是什么?)

->利用 RunTimeAPI动态生成一个字类,并且让instance 对象的isa指针指向这个全新的字类

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

调用顺序

willChangeValueForKey:

父类原来的setter

didChangeValueForKey:

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

使用了KVO监听的对象

中间类的部分伪代码

- 原因:NSKVONotifying_MJPerson重写底层实现,目的:隐藏动态创建的类,不让用户感知
- (Class)class {
    return [MJPerson class];
}
// 伪代码 Function框架
void _NSSetIntValueForKey(){
    [self willChangeValueForKey:@"age"];
    [self setAge:age];
    [self didChangeValueForKey:@"age"];
}
// 通知监听器
- (void)didChangeValueForKey:(NSString *)key {
   [obser observeValueForKeyPath:key ofObject:self change:nil content:nil];
}

-object_getClass(self.person) 和 [self.person class];分别打印什么?为什么?
- object_getClass(self.person); -> NSKVONotifying_MJPerson
- [self.person class];          -> MJPerson

[self.person class]是调用的上面伪代码重写的class方法,

Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();
    else return Nil;
}

getIsa的源码

2.如何手动触发KVO?

   手动调用willChangeValueForKey:和didChangeValueForKey:

3.直接修改成员变量会触发KVO吗?

不会触发KVO,因为其并没有触发setter以及相应的方法

4.通过KVC修改属性会触发KVO吗?

-会触发KVO

-KVC在修改属性时,会调用willChangeValueForKey:和didChangeValueForKey:方法;

5.KVC的赋值和取值过程是怎样的?原理是什么?

setValue:forKey的原理图

- 首先会按照setKey、_setKey的顺序查找方法,找到方法,直接调用方法并赋值;

- 未找到方法,则调用+ (BOOL)accessInstanceVariablesDirectly;

- 若accessInstanceVariablesDirectly方法返回YES,则按照_key、_isKey、key、isKey的顺序查找成员变量,找到直接赋值,找不到则抛出异常;

- 若accessInstanceVariablesDirectly方法返回NO,则直接抛出异常;

(accessInstanceVariablesDirectly 返回yes代表可以访问成员变量)

valueForKey:的原理

- 首先会按照getKey、key、isKey、_key的顺序查找方法,找到直接调用取值

- 若未找到,则查看+ (BOOL)accessInstanceVariablesDirectly的返回值,若返回NO,则直接抛出异常;

- 若返回的YES,则按照_key、_isKey、key、isKey的顺序查找成员变量,找到则取值;

- 找不到则抛出异常;

6.KVC使用场景

-单层字典模型转化 [self.model setValuesForKeysWithDictionary:dict];

-通过KVC修改未暴露的属性

    UILabel *placeholderLabel=[self.userTextField valueForKeyPath:@"placeholderLabel"];
    placeholderLabel.textColor = [UIColor redColor];

-使用valueForKeyPath可以获取数组中国的最大值,最小值,平均值,求和

    CGFloat sum = [[list valueForKeyPath:@"@sum.floatValue"] floatValue];
    CGFloat avg = [[list valueForKeyPath:@"@avg.floatValue"] floatValue];
    CGFloat max = [[list valueForKeyPath:@"@max.floatValue"] floatValue];
    CGFloat min = [[list valueForKeyPath:@"@min.floatValue"] floatValue];

-数组内部去重(@distinctUnionOfObjects.self)

    NSArray *array = [list valueForKeyPath:@"@distinctUnionOfObjects.self"];

-数组合并(去重合并:distinctUnionOfArrays.self、直接合并:unionOfArrays.self)

    NSArray *temp1 = @[@3, @2, @2, @1];
    NSArray *temp2 = @[@3, @4, @5];
    NSArray *unionArr = [@[temp1,temp2] valueForKeyPath:@"@distinctUnionOfArrays.self"];//去重合并
    NSArray *unionAll = [@[temp1,temp2] valueForKeyPath:@"@unionOfArrays.self"];//直接合并

-大小写转换(uppercaseString,lowercaseString)

NSArray *array = @[@"name", @"w", @"aa", @"jimsa"];

NSArray *arrayUpper = [array valueForKeyPath:@"uppercaseString"];

NSArray *arrayLower = [arrayUpper valueForKeyPath:@"lowercaseString"];

-----------------------------------end--------------------------------------

相关文章

  • iOS原理篇(一): KVO实现原理

    KVO实现原理 什么是 KVO KVO 基本使用 KVO 的本质 总结 一 、 什么是KVO KVO(Key-Va...

  • 04. KVO使用,原理,本质

    问题 KVO日常使用 KVO原理(KVO本质是什么) 如何手动触发KVO 直接修改成员变量会触发KVO吗 KVO图...

  • 20.iOS底层学习之KVO 原理

    本篇提纲1、KVO简介;2、KVO的使用;3、KVO的一些细节;4、KVO的底层原理; KVO简介 KVO全称Ke...

  • 深入理解KVO

    iOS | KVO | Objective-C KVO的本质是什么,如何手动触发KVO? 1.什么是KVO KVO...

  • OC语法:KVO的底层实现

    一、KVO是什么二、怎么使用KVO三、KVO的底层实现四、KVO常见面试题 一、KVO是什么 KVO全称Key-V...

  • KVO基本使用

    分三部分解释KVO一.KVO基本使用二.KVO原理解析三.自定义实现KVO 一、KVO基本使用 使用KVO,能够非...

  • KVO 解析

    KVO解析(一) —— 基本了解KVO解析(二) —— 一个简单的KVO实现KVO解析(三) —— KVO合规性K...

  • KVO

    目录 1. KVO的使用1.1 KVO基本使用方法1.2 KVO手动触发模式1.3 KVO属性依赖1.4 KVO容...

  • OC语言之KVO与KVC

    KVO 什么是KVO? KVO 是 Key-value observing(键值观察)的缩写。 KVO是Objec...

  • 可能碰到的iOS笔试面试题(7)--KVO-KVC

    KVC-KVO KVC的底层实现? KVO的底层实现? 什么是KVO和KVC? KVO的缺陷? KVO是一个对象能...

网友评论

      本文标题:KVO

      本文链接:https://www.haomeiwen.com/subject/nqnufltx.html