首先需要说明清楚的是,并不是遇到block捕获引用就得用上weak-strong Dance,只有在出现循环引用的情况下才需要考虑这种做法。【一般在block与目标对象有直接引用关系时很有可能引起循环引用,block与目标对象有间接的相互引用关系也会有可能引起循环引用】
ARC模式下,block会对block内部引用的外部对象进行强引用,如果block本身就是所引用对象里的实例变量,那么会导致循环引用-内存泄漏。
解决的办法之一:在block里把关联对象释放(指针置nil)。但此法风格过硬!
解法二:对引起循环引用的目标对象在block前,新建一个__weak类型的指针引用
,然后把__weak类型的指针穿进block,即可避免循环引用。但此法会导致block执行前,目标对象会被释放,从而无法继续后面操作。故【一般不推荐此法】,但好多人会这么用!循环引用的问题却是不会出现,但同时也引入了新的问题就是,对象释放了,没法做太多的活。
解法三:weak-strong Dance
在block外边依旧新增一个weak类型指针指向可能导致循环引用的节点对象,然后block内部使用一个strong类型(ARC下变量默认的修饰符)的指针指向这个weak类型指针。会产生这么一个现象:使目标对象retain。但由于block没有直接使目标对象retain,而是其内部的函数执行的时候局部变量做的retain,执行完了之后,这个局部变量就销毁了。也就是目标对象也会release,如果其retainCount为0,就会被当即回收。【此为解决循环引用的正确姿势】
思考:由于在block内部使用局部strong类型的指针指向目标对象,确实会使其retian,但是block里边这段代码要是在执行前,目标对象就被释放了,也是同样导致后续操作的执行失效。【这种思考是有误的】
因为对目标对象的retain动作发生在拷贝block到堆区的时候,内存里声明了strong类型的局部变量指向目标对象的时候,就会使之retain。不会导致循环引用就是因为block执行完毕之后(也就是block内部的函数指针指向的函数(block对{}的封装)执行后,局部变量超出作用域,使指向的目标对象release