__weak
本身是可以避免循环引用的问题的,但是其会导致外部对象释放了之后,block 内部也访问不到这个对象的问题,我们可以通过在 block 内部声明一个 __strong
的变量来指向 Obj,使外部对象既能在 block 内部保持住,又能避免循环引用的问题。
__block
本身无法避免循环引用的问题,但是我们可以通过在 block 内部手动把 blockObj 赋值为 nil 的方式来避免循环引用的问题。另外一点就是__block
修饰的变量在 block 内外都是唯一的,要注意这个特性可能带来的隐患。
总结:
1 . 在MRC(手动内存计数)模式下,__block
修饰,可以避免循环引用;ARC(自动内存计数)模式下,__block
修饰,还是会引起循环引用问题;
2 . __block
不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型;
3 . __weak
只能在ARC模式下使用,也只能修饰对象,不能修饰基本数据类型;
4 . __block
对象可以在block中被重新赋值,__weak
不可以;
API Reference对__block变量修饰符的解释,大概意思:
1.__block对象在block中是可以被修改、重新赋值的。
2.__block对象在block中不会被block强引用一次,从而不会出现循环引用问题。
API Reference对__weak变量修饰符的解释,大概意思:
使用了__weak修饰符的对象,作用等同于定义为weak的property。自然不会导致循环引用问题,因为苹果文档已经说的很清楚,当原对象没有任何强引用的时候,弱引用指针也会被设置为nil。
因此,__block和__weak修饰符的区别其实是挺明显的:
1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。
2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。
3.__block对象可以在block中被重新赋值,__weak不可以。
Tips:__unsafe_unretained修饰符可以被视为iOS SDK 4.3以前版本的__weak的替代品,不过不会被自动置空为nil。所以尽可能不要使用这个修饰符。
Block的生命周期管理非常的微妙,与ARC混在一起后,更加复杂。
当Block延stack向上(up)传递的时候,直接返回,编译器会添加[[ copy] autorelease]代码。
当Block延stack向下传递给需要retain的容器的时候,需要显式的调用[^{} copy]方法。
在ARC下,__block修改的NSObject指针依然会被retain。
在ARC下,一个block内引用一个对象的实例变量后,self会被retain,所以极易造成strong reference cycle,可以通过__weak指针来避免这种情形,因为ARC不会为__weak指针retain。