美文网首页
[iOS]关于内存管理的一些总结

[iOS]关于内存管理的一些总结

作者: 未来行者 | 来源:发表于2018-03-31 12:40 被阅读34次

    前言

    内存管理作为iOS最基础的存在,其重要性不言而喻.平时因为忙业务,遇到一些内存相关的问题,然后才有了这篇小结.

    AutoreleasePool

    几个Tips:

    1. AutoreleasePool在非手动添加的情况下,是在当前runloop完了之后才会释放对象.
    2. 子线程的runloop默认不开启,那系统会自动添加AutoreleasePool吗?答案是肯定的,从这篇文章可以看到原理,通过调用autoreleaseNoPage方法来进行处理.
    3. 以new,alloc初始化的对象编译器会自动为这个对象添加release语句,而类似于id object1 = object2;这种会自动包裹一个AutoreleasePool.
    4. 当我们在使用enumerateObjectsUsingBlock这个方法进行遍历的时候,内部也会自动包裹一个AutoreleasePool,所以不需要手动添加.

    循环引用

    这里先给一段代码,两个类TestA,TestB,重写了dealloc方法,便于观察释放与否.TestA内有一个TestB类型的属性b,TestB内有一个TestA类型的属性a.

        TestA *ta = [[TestA alloc] init];
        TestB *tb = [[TestB alloc] init];
        ta.b = tb;//A的b属性指向tb
        tb.a = ta;//B的a属性是想ta
    

    这里毫无疑问会有循环引用,于是自然会想到:

    ta = nil;
    或者
    tb = nil;
    

    但是结果运行之后依然没有打印dealloc方法.这是为什么呢?
    用Leaks分析循环引用关系:


    我们发现循环的链条关键点在于_a_b,我们应该打断这两条蓝线其中的一条.
    ta.b = nil;
    或则
    tb.a = nil;
    

    然后运行发现对象确实被销毁了.
    这里令我百思不得其解的是:ta或者tb都是这个链条的一部分,为什么对他们置为nil不产生效果呢?我尝试这样写:

        ta.b = tb;//A的b属性指向tb
        ta = nil;
        tb.a = ta;//B的a属性是想ta
    

    发现这样也是可以销毁的,道理很简单:循环引用还没建立就销毁一个对象.这样感觉也没有意义.之后和小伙伴们讨论了一下,得出如下值得验证的结论:

    当我设置ta = nil 或者 tb = nil的时候,其实并没有打断这个循环引用的链条,他们的循环引用已经形成了,ta持有b,b的指针指向tb,如果我们要打破这个循环引用首先应该切断指向ta或者tb的指针,也就是ta.b或者tb.a,是这两个指针直接指向的两个对象,切断这种指向才是必要之举.

    其实还有些许迷惑,希望有人能给出一些指点.

    参考资料
    http://blog.sunnyxx.com/2014/10/15/behind-autorelease/
    https://www.jianshu.com/p/f87f40592023

    相关文章

      网友评论

          本文标题:[iOS]关于内存管理的一些总结

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