__block int age = 10;
Block block1 = ^{
age = 20;
};
- 当block在栈上时,并不会对__block变量产生强引用;
- 当block被copy到堆时:
1.会调用block内部的copy函数;
2.copy函数内部会调用_Block_object_assign
函数;
3._Block_object_assign
函数会对__block
变量形成强引用(retain
)。
- 当block从堆中移除时:
1.会调用block内部的dispose
函数;
2.dispose
函数内部会调用_Block_object_dispose
函数;
3._Block_object_dispose
函数会自动释放引用的__block
变量(release
);
copy
block时,__block
变量的变化:
- 在ARC环境下,当block被强引用引用着时,它会自动进行
copy
操作。
- block被
copy
到了堆上,__block int age = 10
按理来说它在栈上的,堆上的指针指向栈上的内存地址 ? 不安全。
- 所以在block被copy到堆上时,它会自动将block内部使用的
__block
变量的内存,也copy到堆上,而且block内部会对这个__block
变量形成强引用。
__block变量为什么有一个指向自己的指针*__forwarding ?
- 以
age
为例:当 __block
变量复制到堆上时,栈上有一个age
,堆上有一个age
,如何确保在block内部给age
赋值时,是赋值给了堆上的age
?
- 当
__block
变量复制到堆上,栈上__block
变量中的__forwarding
指针就会指向堆中的__block
变量,堆中的__forwarding
还是指向自己。赋值的操作是:(age->__forwarding->age) = 20;
- 这样无论你拿到的
age
地址是栈上的还是堆上的,只要通过__forwarding
指针访问到的堆中的age
。
__block修饰对象类型
- 当__block变量在栈上时,不会对指向的对象产生强引用;
- 当__block变量被copy到堆时;
- 会调用__block变量内部的copy函数;
- copy函数内部会调用_Block_object_assign函数;
-
_Block_object_assign
函数会根据所指向对象的修饰符(__strong
、__weak
、__unsafe_unretained
)做出相应的操作,形成强引用(retain
)或者弱引用(注意:这里仅限于ARC时会retain,MRC时不会retain,即:MRC环境下,始终是弱引用
)。
网友评论