iOS KVO

作者: 学不来的凡人 | 来源:发表于2021-04-03 05:55 被阅读0次

kvo:key-value-observing:键值监听,可以监听某个对象属性的值

前言

使用(kvo 监听food属性,使用self.food也可以监听到)

注意:当监听Dog时候,在工程中创建NSKVONotifying_Dog类打印台提示以下,并且监听不起作用
[general] KVO failed to allocate class pair for name NSKVONotifying_Dog, automatic key-value observing will not work for this class

NSLog(@"%@,%@",[dog1 class],[dog2 class]);
// 打印结果 Dog, Dog

//我们可以猜测NSKVONotifyin_ Dog内重写的class内部实现大致为
- (Class) class {
     // 得到类对象,在找到类对象父类
     return class_getSuperclass(object_getClass(self));
}
如果NSKVONotifyin_Dog不重写class方法,那么当对象要调用class对象方法的时候就会一直向上找来到NSObject,而NSObject的class的实现大致为返回自己isa指向的类,返回p1的isa指向的类那么打印出来的类就是NSKVONotifyin_Dog,但是apple不希望将NSKVONotifyin_Dog类暴露出来,并且不希望我们知道NSKVONotifyin_Dog内部实现,所以在内部重写了class类,直接返回Person类,所以外界在调用dog1的class对象方法时,是Dog类。这样dog1给外界的感觉dog1还是Dog类,并不知道NSKVONotifyin_Dog子类的存在。

image.png
@interface ViewController ()
@property (nonatomic,strong)Dog *dog1;
@property (nonatomic,strong)Dog *dog2;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    self.dog1 = [Dog new];//此时 po self.dog1.->isa  Dog
    self.dog2 = [Dog new];
    
    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld;
    [self.dog1 addObserver:self forKeyPath:@"food" options:options context:@"Steven"];
    //此时 po self.dog1.->isa  NSKVONotifying_Dog
//    [self.dog1 removeObserver:self forKeyPath:@"food" context:@"steven"];//此时 po self.dog1.->isa  Dog
    
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    //会触发observeValueForKeyPath的方式
    
    //方式一:.语法常规操作
    self.dog1.food = @"gutou";
    self.dog2.food = @"shi";

    //方式二:直接调用set方法
    [self.dog1 setFood:@"gutou"];
    
    //方式三:配对(必须配对)调用willChangeValueForKey didChangeValueForKey
    [self.dog1 willChangeValueForKey:@"food"];
    [self.dog1 didChangeValueForKey:@"food"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    NSLog(@"\nobject:%@\nkeyPath:%@\nchange:%@\ncontext:%@",object, keyPath, change, context);
}


@end

面试题:

1:ios用什么方式实现对一个对象的kvo?(kvo的本质是什么?)

利用runtimeAPI动态生成一个子类,并让instance对象的isa指向这个全新的类,当修改instance对象的属性时,会调用Foundation的——NSSetXXXValueAndNotify函数:(willChangeValueForKey; 父类原来的setter方法;didChangeValueForKey(内部会触发监听器(observer)的监听方法(observerValueForKeyPath:)),)

2:如何手动触发kvo?
(不调用setage方法)
手动调用willChangeValueForKey 和didChangeValueForKey方法,即可直接触发kvo。

3:直接修改成员变量会触发KVO么?

不会触发KVO,(添加kvo的person实例,其实是NSKVONotyfing_person类,再调用setter方法,不是调用person的setter方法,而是NSKVONotyfing_person的setter方法,因为修改成员变量不是setter方法赋值self.person->age=@"12", 所以就无所谓调用NSKVONotyfing_person类的setter方法,也就不会实现kvo。)

image.png
[图片上传中...(image.png-7e607-1617348136653-0)]
image.png

相关文章

网友评论

      本文标题:iOS KVO

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