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];
};