- 开发以及面试中,经常涉及到使用block的需要注意的问题----循环引用,趁此时机梳理相关block引起循环引用的场景:
- 使用通知(notification) 系统自带的block方法,在block中使用self-->会发生循环引用
TwoVC .m文件
-(void)dealloc {
NSLog(@"%s",__func__);
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
// Do any additional setup after loading the view.
//__weak typeof(self) weakSelf = self; //弱引用
[[NSNotificationCenter defaultCenter] addObserverForName:@"testBlock" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
//__strong typeof(self) strongSelf = weakSelf;
NSDictionary *userInfo = note.userInfo;
NSLog(@"userInfo--%@ -- self.view - %p",userInfo,self.view);
}];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
NSLog(@"%s",__func__);
}
控制台输出
2017-08-02 17:09:31.131 testBlock[36251:3586073] userInfo--{
Project = testNotificationBlock;
} -- self.view - 0x7fff0b501980
2017-08-02 17:09:34.073 testBlock[36251:3586073] -[TwoVC viewWillDisappear:]
结论: 当前VC没有被释放,添加弱引用后,VC被释放掉;存在retain-cycle
- 使用MJRefresh框架中返回上下拉刷新的block方法,在block中使用self-->会发生循环引用
ThreeVC .m文件
-(void)dealloc {
NSLog(@"%s",__func__);
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
self.tableView.dataSource = self;
// __weak typeof(self) weakSelf = self;//(弱引用)
self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
// __strong typeof(self) strongSelf = weakSelf;
NSLog(@"MJrefresh --下拉刷新");
[[NSNotificationCenter defaultCenter] postNotificationName:@"testBlock" object:nil userInfo:@{@"Project":@"testNotificationBlock"}];
[self endrefresh];
}];
[self.tableView.mj_header beginRefreshing];
[self.view addSubview:self.tableView];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
NSLog(@"%s",__func__);
}
控制台输出
2017-08-03 10:39:44.381 testBlock[37278:3717266] MJrefresh --下拉刷新
2017-08-03 10:39:44.382 testBlock[37278:3717266] userInfo--{
Project = testNotificationBlock;
} -- self.view - 0x7f8747406440
2017-08-03 10:39:55.641 testBlock[37278:3717266] -[ThreeVC viewWillDisappear:]
结论: 当前VC没有被释放,添加弱引用后,VC被释放掉;存在retain-cycle
3.强引用自定义的属性block,并在block中使用self-->,会引起循环引用
/** block */
@property (nonatomic, copy) void(^myblock)();
@end
@implementation FourVC
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor yellowColor];
_myblock = ^ {
NSLog(@"--%p",self.view);
};
_myblock();
}
控制台输出
2017-08-03 11:17:51.409 testBlock[37510:3750978] --0x7f8e7d70b460
2017-08-03 11:17:55.696 testBlock[37510:3750978] -[FourVC viewWillDisappear:]
结论: 1)报警告 2)当前VC没有被释放,添加弱引用后,VC被释放掉;存在retain-cycle
未完待续,欢迎指正/添加
测试代码奉上