zoukankan      html  css  js  c++  java
  • Block 的循环引用

    Block是在栈上生成的,所以一般使用copy方法把Block复制到堆上,避免Block被立刻释放。

    Block会对内部的变量形成强引用,而如果同时该变量又持有这个Block,就会导致循环引用而无法释放,从而导致内存泄露。

    最常见的就是self持有Block,而又在Block内部调用self的方法或属性,那selfBlock就会形成循环引用而无法释放。由于我们习惯在dealloc中释放对象,但是即使在dealloc中将Block释放也没用,因为selfdealloc根本不会跑进去。比如:

    1 self.MyBlock = ^void(){
    2  
    3   [self doSomething];
    4 };

    其实,最简单的解决方法就是在self的某个非dealloc方法中将Block主动释放,并在需要释放self之前调用这个方法,这样才能有效的解除引用。但是这种方法使用起来比较麻烦,而且很容易忘记调用。

    所以我们一般是在Block中使用弱引用的self。下面分别介绍ARCMRC中在Block中使用弱引用self的方法。

    ARC

    1 __weak typeof(self) weakSelf = self;
    2  
    3 self.MyBlock = ^void(){
    4  
    5 __strong typeof(self) strongSelf = weakSelf;
    6  
    7   [strongSelf doSomething];
    8 };

    这样做的好处是不必在Block直接使用self,这样就不会对self进行强引用,只要self需要释放,self就会自动释放,Block也会自动释放。ARC中,进入Block前,需要使用__weakself进行弱引用,并在Block中使用__strongweakSelf进行强引用。

    这样做的另一个好处是,在ARC中使用__weak之后,如果self在某个地方被释放了,那weakSelf也会被自动置为nil,这样即使在Block中使用weakSelf,也不会访问错误。

    而在Block中使用__strong则是为了避免在使用Block的过程中self被释放导致访问出错。

    MRC


    1
    __block typeof(self) blockSelf = self; 2 3 self.MyBlock = ^void(){ 4 5   if (!malloc_zone_from_ptr(blockSelf)) 6   return; 7 8   __strong typeof(self) strongSelf = blockSelf; 9 10   [strongSelf doSomething]; 11 };

    其实,MRC的基本思路和ARC是一样的。有两处不同:

    1. MRC中使用__block而不是__weak进行弱引用,因为在ARC中使用__block会对该对象进行强引用。

    2. MRCBlock中使用malloc_zone_from_ptr()方法判断blockSelf是否已经被释放,因为MRC不会对已释放的对象自动置为nil


    可见,无论是MRC还是ARC,解决方法都是类似的。虽然Block的使用增加了简洁性和便利性,但使用Block的过程中也要时刻注意避免内存泄露。

    How Do I Declare A Block in Objective-C? 总结了声明Block的几种格式,在开发过程中可以参考使用。

  • 相关阅读:
    Use MusicBrainz in iOS(三)查询专辑的完整信息
    内存寻址一(分段)
    POJ 1018 Communication System (动态规划)
    利用Eclipse中的Maven构建Web项目(二)
    cocos2d-x2.2.3学习
    (排序算法整理)NEFU 30/32
    POJ 1066 昂贵的聘礼
    2014年腾讯暑假实习软件开发笔试题汇总
    Android学习之——自己搭建Http框架(1)
    C 语言之预处理 ---------文件包括
  • 原文地址:https://www.cnblogs.com/coltfoal/p/4763540.html
Copyright © 2011-2022 走看看