Block 访问成员变量
答案是肯定会造成强引用,和属性变量一样的结果,只不过比较隐形;
解决方案有很多:1、把成员变量改成属性,通过weakSelf调;2、(也是苹果文档里说的)声明一个局部变量接一下_block 来修饰,在block里用这个局部变量;
__weak typeof(self)weakSelf = self;
_block NSString *local_about = _about;
item.cellSelectBlock = ^(NSIndexPath *path){
ProtocolHTMLController *htmlVC = [[ProtocolHTMLController alloc]init];
htmlVC.requesURL = local_about; // 使用
[weakSelf.navigationController pushViewController:htmlVC animated:YES];
};
案例如下:
问题
ViewController 中定义成员变量如下:
@implementation EHISalesLeadsListViewController {
__block NSString *pageNum;
}
使用如下:
self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
pageNum = @"1";
}];
在这里,该 ViewController 消失时并没有走 dealloc 释放。
成员变量和属性都是 self 引用的变量。
成员变量:一般直接使用,不需要使用
self
引用(也可以使用self->
引用);
属性:一般都使用self.
引用(也可以使用下划线_
);
所以在 Block 中,属性一般会保持习惯使用 self.
引用,而成员变量容易忘记使用 self->
引用。
在上面,因为 self
强引用 tableView
,tableView
强引用 Block
,Block
内使用 self
的成员变量 pageNum
。鉴于上面这句话,因此代码中虽然没有写 self->
引用,也会已经强引用 self
了。因为都是强引用,三者形成循环引用,内存泄露。
所以,我们要打破循环引用。
2.1 weakSelf
打破循环引用要使其中一方为 weak
弱引用,通常我们会在 Block
外先把 self
weak
掉,再在内部使用,如下:
@weakify(self)
self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
@strongify(self)
self->pageNum = @"1";
}];
2.2 声明__block 修饰
可以使用 __weak
指向成员变量解决循环引用,也可以使用 __block
来解决。因为这里要修改变量的值,所以只能使用 __block
:
__block NSInteger blockPageIndex = pageIndex;
self.tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{
blockPageIndex ++;
}];
3. 成员变量是否声明 __block 并没有影响
@implementation EHISalesLeadsListViewController {
__block NSString *pageNum;
}
前面在声明成员变量的时候使用 __block
修饰了,经过试验,完全没有作用,没有影响。