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

  • 开发以及面试中,经常涉及到使用block的需要注意的问题----循环引用,趁此时机梳理相关block引起循环引用的场景:
  1. 使用通知(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
  1. 使用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

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

你可能感兴趣的:(梳理易引起retain-cycle的场景(使用block))