KVO本质

作者: Berning | 来源:发表于2021-02-27 16:15 被阅读0次
@interface NSPerson : NSObject

@property(nonatomic,assign)int  age;
@property(nonatomic,assign)double  height;

@end

@implentation NSPerson
- (void)setAge:(int)age
{
    _age = age;
}
@end


@interface ViewController ()
@property(nonatomic,strong)NSPerson *person;
@end

@ implentation viewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.person = [NSPerson new];
    self.person.age = 10;
    self.person.height = 180;
}
@end

本质

  • runtime动态生成子类NSKVONotifying_NSPerson
  • 修改了setAge:方法
    IMP imp = [self.person methodForSelector:@selector(setAge:)];
    IMP imp2 = [person2 methodForSelector:@selector(setAge:)];
Printing description   of imp:
(IMP) imp = 0x00007fff258f10eb (Foundation`_NSSetIntValueAndNotify)
Printing description of imp2:
(IMP) imp2 = 0x00000001059716e0 (KVO`-[NSPerson setAge:] at NSPerson.h:15)
(lldb) 

//伪代码
@implentation NSKVONotifying_NSPerson
- (void)setAge:(int)age
{
    _NSSetIntValueAndNotify();
}

void  _NSSetIntValueAndNotify()
{
    [obj willChangeValueForKey:@"age"];
    [super setAge:age];
    [obj didChangeValueForKey:@"age"];
}

- (void) didChangeValueForKey:(NSString *)key
{
    [observer observeValueForKeyPath:@"age" ofObject:obj 
    change:@{old, new }  context:nil];
}

@end

子类

- (void)printMethodListForClass:(Class)cls
{
    unsigned int count;
    Method *methodList = class_copyMethodList(cls, &count);
    NSMutableString *methodString = [NSMutableString string];
    for (int i = 0; i < count; i++) {
        Method method = *(methodList + i);
        NSString *methodName = NSStringFromSelector(method_getName(method));
        [methodString appendFormat:@"%@,",methodName];
    }
    
    free(methodList);
    
    NSLog(@"%@",methodString);
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.person = [NSPerson new];
    self.person.age = 10;
    self.person.height = 180;

    NSPerson *person2 = [NSPerson new];
    person2.age = 20;
    person2.height = 175;
    
    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;

    [self.person addObserver:self forKeyPath:@"age" options:options context:nil];
    [self.person addObserver:self forKeyPath:@"height" options:options context:nil];

    [self printMethodListForClass:object_getClass(self.person)];
    [self printMethodListForClass:object_getClass(person2)];
}

log

KVO[71463:2802731] setHeight:,setAge:,class,dealloc,_isKVOA,
KVO[71463:2802731] height,setHeight:,age,setAge:,

NSKVONotifying_NSPerson生成了下面方法

  • setAge:
  • class
- (Class)class
{
    return [NSPerson class];
}
  • dealloc
  • _isKVOA
- (BOOL) _isKVOA
{
    return YES;
}

手动触发

    [self.person willChangeValueForKey:@"age"];
    [self.person didChangeValueForKey:@"age"];

相关文章

  • Objective-C的本质(4)—— KVO本质

    参考:iOS底层原理总结 - 探寻KVO本质iOS-KVO本质 问题一:kvo如果找到对应的属性 KVO不存在查找...

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

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

  • 深入理解KVO

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

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

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

  • KVO

    0:KVO的使用步骤 1:KVO本质 methodForSelector方法 NSKVONotifying_Per...

  • 探索中的KVO

    探索KVO的本质 什么是KVO KVO的全称就是Key-Value Observing ,俗称“键值监听”。用于监...

  • KVO本质

    kvo本质是监听对象有没有调用set方法。假如对象属性是直接通过赋值方式改变的,则不会触发KVO机制。

  • KVO本质

    本质 runtime动态生成子类NSKVONotifying_NSPerson 修改了setAge:方法 子类 l...

  • KVO本质

    实现过程:对一个person类的实例对象A的一个属性添加kvo之后,会在runtime时生成一个person类的子...

  • KVO本质

    面试题: 简单使用: 发现:直接修改成员变量会 是不会触发KVO的.//分析:NSDictionary

网友评论

      本文标题:KVO本质

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