美文网首页
KVO学习笔记

KVO学习笔记

作者: 蒲公英守候_c082 | 来源:发表于2019-05-08 19:34 被阅读0次

1.KVO初探学习
2.KVO 底层原理探索

1.KVO初探学习

//先来一个三部曲操作
[self.person addObserver:self forKeyPath:@"name" options:(NSKeyValueObservingOptionNew) context:"person_name"];
// options是个枚举 NSKeyValueObservingOptionNew
//               NSKeyValueObservingOptionOld
//               NSKeyValueObservingOptionInitial
//               NSKeyValueObservingOptionPrior

//  context 参数 是个标签 用来区分 防止多继承的时候会出现问题  并且它的查找更优越(性能高,嵌套少) 
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
  self.person.name = @"SB";
}

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

- (void)dealloc
{
    [self.person removeObserver:self forKeyPath:@"name"];
}

移除观察者的重要性 (IOS11之后说不移除是不对的 ),从表象上市看不出来问题的,如果当你使用单例的时候,分别在两个控制器,一个初始化,一个单例,会调用两次,问题很大(必须移除),同时单例也会导致崩溃3
FKDetailViewController :{
kind = 1;
new = "hello word";
}
2019-05-05 18:52:09.932175+0800 001---KVO初探[17802:2935771] {
kind = 1;
new = "hello word";
} -- <FKStudent: 0x600003d49d40>

KVO 也分 手动观察 - 自动观察两种

//自动
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key{
    return YES;
}
// 手动观察需要下面 willChange 和 didChange 方法
- (void)setName:(NSString *)name{
    
    [self willChangeValueForKey:@"name"];
    _name = name;
    [self didChangeValueForKey:@"name"];
}

集合类型的观察,一定需要通过KVC来,不然是取不到值的

//    取值和赋值过程和普通类型不一样   行不通
//    [self.person.dataArray addObject:@"joo"];
//    KVC  -- 设置值流程  dataArray 是数组
    [[self.person mutableArrayValueForKey:@"dataArray"] addObject:@"hello"];

2.KVO 底层原理探索

1.KVO会默认观察setter方法

po object_getClass([self person])  //person  是 FKPerson
NSKVONotifying_FKPerson(动态类)  //当前这个对象不再指向原来的person 而是指向了 NSKVONotifying_对象名
不是类的isa 而是当前对象的isa

现在有两个问题
1.NSKVONotifying_FKPerson 是什么时候生成的?
2.NSKVONotifying_FKPerson 和 FKPerson 是什么关系

可以先调用一下下面这个方法
[self printClassAllMethod:[FKPerson class]];
[self printClassAllMethod:NSClassFromString(@"NSKVONotifying_FKPerson")];//如果在一开始没添加KVO时就调用这个类是不存在,会导致崩溃,如果在添加完KVO之后,调用会进行打印

#pragma mark - 遍历类以及子类
- (void)printClasses:(Class)cls{
    
    /// 注册类的总数
    int count = objc_getClassList(NULL, 0);
    /// 创建一个数组, 其中包含给定对象
    NSMutableArray *mArray = [NSMutableArray arrayWithObject:cls];
    /// 获取所有已注册的类
    Class* classes = (Class*)malloc(sizeof(Class)*count);
    objc_getClassList(classes, count);
    for (int i = 0; i<count; i++) {
        if (cls == class_getSuperclass(classes[i])) {
            [mArray addObject:classes[i]];
        }
    }
    free(classes);
    NSLog(@"classes = %@", mArray);
}

classes = (
FKPerson,
"NSKVONotifying_FKPerson"
)
这是打印结果, 根据printClasses方法就能知道 NSKVONotifying_FKPerson 是 FKPerson 的子类~~~
KVC动态创建NSKVONotifying_XX类,修改被监听对象isa指针指向,只要调用对象的set方法,
就会调用NSKVONotifying_XX的set方法 (说到底就是对象的set方法有没有调用)

然后说一下他的类方法(methodList)里面发生了那些变化

- (void)printClassAllMethod:(Class)cls{
    unsigned int count = 0;
    Method *methodList = class_copyMethodList(cls, &count);
    for (int i = 0; i<count; i++) {
        Method method = methodList[i];
        SEL sel = method_getName(method);
        IMP imp = class_getMethodImplementation(cls, sel);
        NSLog(@"%@-%p",NSStringFromSelector(sel),imp);
    }
    free(methodList);
}
// 分别调用
[self printClassAllMethod:[FKPerson class]];
[self printClassAllMethod:NSClassFromString(@"NSKVONotifying_FKPerson")];

打印结果

这是FKPerson
2019-05-07 20:00:39.062279+0800 002---KVO原理探讨[32229:4023419] word-0x10e490650
2019-05-07 20:00:39.062457+0800 002---KVO原理探讨[32229:4023419] heelo-0x10e490640
2019-05-07 20:00:39.062564+0800 002---KVO原理探讨[32229:4023419] .cxx_destruct-0x10e490690
2019-05-07 20:00:39.062664+0800 002---KVO原理探讨[32229:4023419] setNickName:-0x10e4905e0
2019-05-07 20:00:39.062759+0800 002---KVO原理探讨[32229:4023419] nickName-0x10e490660
这是NSKVONotifying_FKPerson
2019-05-07 20:00:42.644459+0800 002---KVO原理探讨[32229:4023419] setNickName:-0x10e7ebd1a
2019-05-07 20:00:42.644649+0800 002---KVO原理探讨[32229:4023419] class-0x10e7ea74e
2019-05-07 20:00:42.644830+0800 002---KVO原理探讨[32229:4023419] dealloc-0x10e7ea4f2
2019-05-07 20:00:42.645011+0800 002---KVO原理探讨[32229:4023419] _isKVOA-0x10e7ea4ea

可以看到
1.他重写的setter 方法
2.添加了class
3.析构dealloc
4._isKVOA (KVO标志)

相关文章

  • KVC、KVO的本质

    这篇文章介绍KVC、KVO的本质。如果你对KVC、KVO不了解,推荐先查看其用法:KVC和KVO学习笔记[http...

  • KVO学习笔记

    KVO KVO 操作需要三步完成 (KVO是观察者设计的一个模式) 第一步:添加一个观察者(在viewDidLoa...

  • KVO学习笔记

    使用时小技巧 一、自动开关automaticallyNotifiesObserversForKey:,如果返回NO...

  • KVO学习笔记

    1.KVO初探学习2.KVO 底层原理探索 1.KVO初探学习 移除观察者的重要性 (IOS11之后说不移除是不对...

  • OC底层学习笔记(3)-KVO的实现

    注:文章为自己学习李明杰老师的OC底层视频做的随手笔记 什么是KVO? KVO的全称是key-value obse...

  • iOS面试题(4) KVO KVC

    声明,不是原创,笔记均来自 群主大神~ 手动实现KVO 什么是KVO和KVC? KVO内部实现原理 NSNotif...

  • KVO的浅显理解

    近两天看视频教程,粗略的学习了一下KVO的使用。做个笔记,以便后期自己查阅。KVO的实质则是通过iOS的runti...

  • KVO学习

    KVO机制学习 什么是KVO?   KVO是Key-Value-Observing的缩写,通过KVO机制对象可以得...

  • KVC和KVO学习笔记

    在编程中,最常见的就是程序的流程取决于你所使用的各种变量和属性的值,根据变量和属性的值确定后面运行的代码,有时会检...

  • OC的KVO学习记录(2)

    仿写KVO的实现KVO原理参考可前一篇OC的KVO学习记录代码github地址:Sameny仿写KVO 注:关键代...

网友评论

      本文标题:KVO学习笔记

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