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

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

但如果后面还跟有一个刷新重新加载的功能?

而这个重新调用reloadData的地方,可能跟block不在同一个函数,比如代码像这样:


-(void)start
{
 BlockTable *table=[BlockTable new];
 self.table=table;//搞到全局变量中
 table.addCell = ^{
 __weak typeof(table) this=table;
 NSLog(@"addCell call");
 };
 [table reloadData];
 NSLog(@"table retain = %ld",CFGetRetainCount((__bridge CFTypeRef)(table)));
}
-(void)reflesh
{
 [self.table reloadData];
}

给外面的类定义了一个table属性,然后调用完start后再调用reflesh,运行,会怎样呢?

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

出现了IOS上最可怕的EXC_BAD_ACCESS 野指针错误。

对于block离开函数后,消亡了容易理解,只是这里:

这什么是直接抛异常?哥不是作了判断了么?

让我们换种代码写法:

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

另外从上图看:_addCell还是有值的。

为什么if(self.addCell)判断就直接死,if(_addCell)却没死呢?

正常self.addCell正常不是也return _addCell么?

这个问题,留给让你们思考了。

最可怕的,还是下面的这段话:

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

7:避开野指针,仍是弱引用,功能不变

OK,继续发挥想象力,看看怎么避开野指针,同时还是实现上述的效果:

1:把block属性从copy改成weak


@property (nonatomic,weak)AddCellBlock addCell;

2:赋值代码手工copy:


-(void)setAddCell:(AddCellBlock)addCell
{
 addCell=[addCell copy];
 _addCell=addCell;
 //_addCell=[addCell copy];这样简写是不行的,不明白为虾米呢
 
 // 原来是这样写的:
 // __weak AddCellBlock addCellWeak=addCell;
 // _addCell=addCellWeak ;
}

再次运行,神奇的事情发生了:

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

流程还是很顺,不会有野批针异常,Table也释放了。