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的循环引用的。

  • 相关阅读:
    查看MAC系统JRE和JDK版本
    【转】频点CTO张成:基于Cocos2d的MMORPG开发经验
    Android上常见度量单位【xdpi、hdpi、mdpi、ldpi】解读
    常见android手机分辨率(xxhdpi,xhdpi)
    Android市场官方的统计信息
    【转】腾讯分析移动设备屏幕分辨率分析报告-(数据基于2012年12月至2013年1月上半月)
    error “base class has incomplete type”
    Eclipse 各种包说明
    怎么鉴别五帝钱真假
    【jzoj 6276】树(线段树)(扫描线)
  • 原文地址:https://www.cnblogs.com/sunshine-anycall/p/4780356.html
Copyright © 2011-2022 走看看