__weak
block内的 weakObj 和 block外的weakObj 不是同一个变量。
block捕获了weakObj,同时也对obj进行了弱引用。当在block外把obj释放之后,block内也读不到这个变量了。
当obj = nil时,block内的weakObj 也为nil 了。也就是说,obj实际上是被释放了。可见__weak是可以避免循环引用的问题的。
但是,在AFNetworking的源码中,会发现作者把变量在block外面先用__weak声明,在block内把前面weak声明的变量赋值给__strong修饰的变量。
这种写法的好处就是可以让变量在block内部安全可用,即使外部释放了,也会在blokc的生命周期内保留该变量。
这种写法既避免了循环引用的问题,又可以在block内部持有该变量。
__block
__block实际上是把变量的作用域给改变了。应该是提升了变量的作用域,使得blokc内部和外部所访问的是同一个变量。
类似于声明了一个static 和 globan变量的意思。
blockObj在地址在前后是有变化的,也就是说blockObj应该是block内部提升的作用域。
当外部的obj = nil 的时候,obj理应被释放,但实际上blockObj仍然强引用着obj,obj其实并没有真正被释放。因此使用_block并不能避免循环引用的问题。
但是我们可以通过手动去释放blockObj的方式来释放obj。这样就可以在block内部能够访问到obj,又可以避免循环引用的问题。但是这种方法不完美。
1、必须记住在block底部释放block变量,这其实和MRC有些类似了。
2、挡在block外部修改了blockObj的值的时候,block内部的值也会改变,反之在block内部修改blokcObj在外面使用时,值也会发生改变。这就可能会因为不小心从而带来安全隐患。
3、_blokc其实是提升了变量的作用域,在block内部访问的都是同一个blockObj可能会造成一些隐患。
总结:
__weak 本身是可以避免循环引用的问题的,但是其会导致外部对象释放了之后,block 内部也访问不到这个对象的问题,我们可以通过在 block 内部声明一个 __strong 的变量来指向 weakObj,使外部对象既能在 block 内部保持住,又能避免循环引用的问题
__block 本身无法避免循环引用的问题,但是我们可以通过在 block 内部手动把 blockObj 赋值为 nil 的方式来避免循环引用的问题。另外一点就是 __block 修饰的变量在 block 内外都是唯一的,要注意这个特性可能带来的隐患。