美文网首页程序员
[iOS]KVOController踩坑记

[iOS]KVOController踩坑记

作者: 退役程序员Franco | 来源:发表于2017-12-15 15:39 被阅读222次

    KVO 作为 iOS 中一种强大并且有效的机制,为我们检测对象属性的变化提供了帮助;

    但系统提供的KVO接口实在太麻烦,所以开发过程中,我们使用了facebook 开源的KVOController

    今天和大家分享一下在项目开发过程中KVOController的填坑经历。

    第一个坑:

    这样使用会导致selfKVOController形成循环引用。

    1. KVOController为所有的NSObject对象都提供 -KVOController 属性,所以这里self是强引用了KVOController

    2.     FBKVOController 实例方法-observer:keyPath:options:block: 调用后会强引用 self 

    [_objectInfosMap setObject:infos forKey:object];

    这里的 object 就是 -[KVOController observer:keyPath:options:block:] 传进来的第一个参数,也就是"self"

    也就是把 “self” 作为 key,保存在FBKVOController的私有变量_objectInfosMap里面

    就会形成 “self ----》 KVOController ----》 self” 这样的循环引用


    第二个坑:

    为了解决上面的循环引用问题,我把代码改成了下面酱紫,iOS10必崩

    KVOControllerNonRetainingKVOController 的区别就是初始化的时候,retainObservedNO

    上面“坑一”说到,“self” 是被 _objectInfosMap 强引用了,retainObserved 传 NO,就可以解决这个问题

    但是事情并没有这样结束。接下来的测试,ios10的系统必崩

    这是 "self" 释放了,但是没有调用到 removeObserver 的崩溃栈

    -[FBKVOController _unobserveAll] 里面调试,发现 _objectInfosMap 中已经没有了 “self”

    调用顺序是这样的:

    1. [self dealloc]

    2. [FBKVOController dealloc]

    3. [FBKVOController dealloc] 里面找存起来的"self",并调用 [self removeObserver] 

    因为第3步中,“self”已经被释放,FBKVOController 中对“self” weak 指针已经置 nil

    所以最终并没有调用到 “self” 的 removeObserver

    总结:

    一、对象监听自己的属性变化,应该在setter中监听;而不应该使用 -[self.KVOController observe:self]

    二、对象dealloc时,指向对象的weak指针已经置为nil

    相关文章

      网友评论

        本文标题:[iOS]KVOController踩坑记

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