zoukankan      html  css  js  c++  java
  • iOS的block内存管理

    初始情况下:

    block本身、__block修饰的变量以及在block内部使用的变量都是在栈里的。

    __block修饰的变量的地址会作为实参传入block块内部(暂时先这么理解,实际比较复杂)。block使用的外部变量被const拷贝到了block内部。也就是block使用的外部变量和这个外部变量本身没有关系。

    copy方法之后

    被拷贝的方法还是在栈上。但是拷贝之后的block已经被放在了heap(堆)上。同时__block修饰的变量被移动到了堆上,原来在栈上的已经不存在。还有block的外部变量的const拷贝也被拷贝到了堆上。

    如果block块使用的外部变量是一个refernce的对象,那么这个对象的引用计数会增加1。

    堆上的block再做一次copy之后,只是引用计数增加1,但是不会重新再做拷贝动作。

    retain操作

    由于retain是有返回值的。retain要求返回的地址和调用对象的地址一致。但是block的地址可能是会变的(尤其是从栈到堆的过程),所以对block做retain操作是没有用处的。什么都不会做!

    销毁(或内存回收时)

    heap上的block块先于stack上的被销毁时,如调用release销毁堆上的block块。heap中的block块在引用计数变为0的时候被销毁。而__block修饰的变量还在heap中,因为stack还要使用,同时栈上的block快也要使用。

    当heap上的block块晚于stack时,stack会被清除。在heap中的block块在调用release减少引用计数到0的时候释放内存。

    block和Objective-C对象

    如果对block做拷贝操作,block会对其内部使用的对象生成强引用。

    如果在block块内部使用了:

    1. 以引用的方式使用了类的成员变量,那么这个block会对self产生强引用。
    2. 以值得方式使用了类的成员变量,那么这个block会对这个变量本身产生强引用。

    例如:

    dispatch_async(queue, ^{
        // instanceVariable is used by reference, a strong reference is made to self
        doSomethingWithObject(instanceVariable);
    });
     
     
    id localVariable = instanceVariable;
    dispatch_async(queue, ^{
        /*
          localVariable is used by value, a strong reference is made to localVariable
          (and not to self).
        */
        doSomethingWithObject(localVariable);
    });

    以上可以通过__block修饰符来改变。是的__block是另外的一种存储类型,就像copy、retain什么的。这样这个引用就直接被传递到了block中。

    但是__block是不可以用来消除对self的循环引用的。

  • 相关阅读:
    南阳ACM 题目811:变态最大值 Java版
    南阳ACM 题目811:变态最大值 Java版
    南阳ACM 题目517:最小公倍数 Java版
    南阳ACM 题目517:最小公倍数 Java版
    Jquery学习总结(4)——高效Web开发的10个jQuery代码片段
    Mysql学习总结(34)——Mysql 彻底解决中文乱码的问题
    MyBatis学习总结(19)——Mybatis传多个参数(三种解决方案)
    Git学习总结(10)——git 常用命令汇总
    Spring MVC学习总结(7)——Spring MVC整合Ehcache缓存框架
    Mysql学习总结(33)——阿里云centos配置MySQL主从复制
  • 原文地址:https://www.cnblogs.com/sunshine-anycall/p/4780356.html
Copyright © 2011-2022 走看看