Block内存问题

2017-03-09  本文已影响11人  爆炸的白菜君
  int a = 10;
  void(^block)() = ^{
        a=20;
  };
  block();

这种写法会报错,因为在block中使用的a相当于是一个常亮10,在runtime语句中是将a作为一个常亮在传递就是10,这样就讲得通为什么会报错。因为10不可能被赋值成20

__block int a = 10;
void(^block)() = ^{
    a=20;
};
block();

这种写法就是正确的写法,因为Runtime中是将block中的a作为一个指针在传递,对一个指针是可以做赋值操作的,拿到a的地址将里面的内容修改成20.

内存管理

block是存在一栈中的

__block int a = 10;
void(^block)() = ^{
 a=20;
 };
block();

对block进行copy操作之后就会把block拷贝到堆内存中(MRC写法)

__block int a = 10;
void(^block)() = ^{
  a=20;
};
Block_copy(block);
block();

为什么要对Block进行copy操作呢?
因为如果不对Block进行Copy操作的话block会在栈区,栈区的内存不受开发者管理,所以很容易就被释放掉,不稳定。copy到堆区以后就,block的释放就完全受制于开发者,所以要对block进行copy操作。

Block的循环引用问题

Dog *dog = [[Dog alloc] init];      
 dog.block = ^(){
   [dog run];
};

这段代码就出现了循环引用。
dog对象持有block,block中也持有dog对象
解决办法

MRC

__block Dog *dog = [[Dog alloc] init];
dog.block = ^(){
    [dog run];
};

__block修饰以后就告诉block不要对这个对象持有(做retain操作)

ARC

__weak Dog *dog = [[Dog alloc] init];
 dog.block = ^(){
   [dog run];
};
__unsafe_unretained Dog *dog = [[Dog alloc] init];
dog.block = ^(){
   [dog run];
 };
上一篇下一篇

猜你喜欢

热点阅读