美文网首页iOS 开发
iOS中Block在ARC中循环引用的原因和解决方法

iOS中Block在ARC中循环引用的原因和解决方法

作者: cj小牛 | 来源:发表于2016-05-11 15:53 被阅读887次

    经常听说block的循环应用,就是说的A引用B ,B又引用A,这样的交叉引用,导致AB都不能释放,后果就是,内存会增加,甚至导致程序崩溃。
    下面通过代码来看产生的原因
    首先定义一个Friend的类
    1.1 Friend.h文件

    import <Foundation/Foundation.h>

    @interface Friend : NSObject
    @property(nonatomic ,copy) void(^testBlock)();
    -(void)run;
    @end

    1.2 Friend.m文件

    import "Friend.h"

    @implementation Friend
    添加了一个run的测试的方法
    -(void)run {
    NSLog(@" person run");
    }
    -(void)dealloc{
    NSLog(@"friend被释放了");
    }

    2.0 在viecontroller.m文件中

    • (void)viewDidLoad {
      [super viewDidLoad];

      Friend *p = [[Friend alloc]init];
      p.testBlock =^{
      这个时候系统就会产生警告,产生了循环引用
      [ p run];
      };
      }
      3 下面来讨论产生循环引用的原因
      3.1
      Friend p = [[Friend alloc]init]; 这句代码的解释是
      当实例化一个对象的时候 这个对象的
      p 指针放在栈内存中,
      对象p存放在堆内存中。
      3.2 @property(nonatomic ,copy) void(^testBlock)();
      当我们声明一个block的成员变量的时候,这个block成员变量存放在栈中,
      但我们调用这个block用的的是copy属性 (如果没有对block用copy,block存放 在栈内存控件中),这个block就会转移到堆中,这样就会对在block中的对象产生强引用。 那么执行这句代码的时候。堆空间中的block会指向在p这个对象中用的block,这样block就会对对象p产生一个强引用,但是testblock 也是P的成员属性。 所以循环引用就产生了。
      p.testBlock =^{
      [ p run];
      };

    二 Block中的循环应用的处理方法

    • (void)viewDidLoad {
      [super viewDidLoad];

      Friend *p = [[Friend alloc]init];
      下面这两句代码任选一句就可以了,但是官方推荐选用第一句

      __weak typeof (p) weakp = p;
      __unsafe_unretained typeof (p) weaka = p ;
      p.testBlock =^{
      [weakp run];
      };

    }

    相关文章

      网友评论

        本文标题:iOS中Block在ARC中循环引用的原因和解决方法

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