一篇文章让你看懂IOS中的block为何再也不需要WeakSelf弱引用

2020-01-21 04:05:19王旭

计数器仍为2,而且也释放了。

经过思考,出来了以下的结论:

     1:块的定义本身,就会造成1次引用,不过这次引用,在块离开所在的函数时,释放时,抵消掉引用数。

     2:存档块的时候,会造成1次引用,而这个引用,是内存无法释放的原因。

4:根据上述解释,得到一个疯狂的结论:

只要block的代码只执行1次的,都可以任性的self或其它强引用。

事实上,我们写的代码,很多block的确只执行一次,不管是传的时候就执行,还是传完之后过段时间回调再执行。

认定只要执行1次的,就不需要WeakSelf,除非第三方框架的设计者造孽留坑,忘了在存档block执行后补上block=nil这一刀。

5:消灭赋值的引用计数:

继续发挥想象力,既然存的时候,会增加一次引用,辣么,让它不增加引用不就好了:


@implementation BlockTable
-(void)setAddCell:(AddCellBlock)addCell
{
 __weak AddCellBlock addCellWeak=addCell;
 _addCell=addCellWeak;
}

我们先给这个block定义一个弱引用,然后再赋值给_addCell,运行看看:

ios,block,weakself,weak,self,弱引用self

哇草,成功了!计数器为2,正常释放了,看来自己的想象力,还是可以的!!

接下来,我们补充完善一下代码,增加一个reloadData方法,方法里调用事件。

完整的代码如下:


@interface BlockTable : NSObject
typedef void (^AddCellBlock)();
@property (nonatomic,copy)AddCellBlock addCell;
-(void)reloadData;
@end
@implementation BlockTable
-(void)setAddCell:(AddCellBlock)addCell
{
 __weak AddCellBlock addCellWeak=addCell;
 _addCell=addCellWeak;
}
-(void)reloadData
{
 if(self.addCell)
 {
 self.addCell();     self.addCell();//没事来两次,模拟table多次循环清加cell
 }
}
-(void)dealloc
{
 NSLog(@"Table relase");
}
@end

修改一下增加日志输出,现在再执行一下看看:

ios,block,weakself,weak,self,弱引用self

一切看起来都相当完美,不需要引入第三,需要多次使用的,只是在存的时候,存个弱引用,就搞定了。

6:弱引用降低计数的缺陷:

块的定义,和使用的场景,必须在同一个函数。

说白了就是块离开函数体就会消亡,所以要用要赶紧,且用且珍惜。

正常一个Table写完代码reloadData后,数据出来了。