梳理易引起retain-cycle的场景(使用block)

  • 开发以及面试中,经常涉及到使用block的需要注意的问题—-循环引用,趁此时机梳理相关block引起循环引用的场景:
  1. 使用通知(notification) 系统自带的block方法,在block中使用self–>会发生循环引用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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__);
    }

控制台输出

1
2
3
4
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

  1. 使用MJRefresh框架中返回上下拉刷新的block方法,在block中使用self–>会发生循环引用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    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__);
    }

控制台输出

1
2
3
4
5
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–>,会引起循环引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/** block */
@property (nonatomic, copy) void(^myblock)();
@end
@implementation FourVC
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor yellowColor];
_myblock = ^ {
NSLog(@"--%p",self.view);
};
_myblock();
}

控制台输出

1
2
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

未完待续,欢迎指正/添加
测试代码奉上