26
2017
09

ARC环境下循环引用案例

虽然ARC环境帮助我们做了很多事情,完美的解决了大多数情况下对象的自动释放。但在使用black的情况下,如果不注意,循环引用还是会发生的,导致对象无法释放。

循环引用发生不一定会造成直观的现象,但某些场景下却会带来问题,比如在某个 Controller 注册了 self 为观察者,一般会在 dealloc 中移除观察者。但如果页面无法释放,再次进入这个 Controller 就会重复注册观察者,会出现通知重复调用的问题。

案例一:

[self.model doSomething:^(NSNumber *id) {
    self.name = [NSString stringWithFormat:@"我的 id 是%@",id];
}];

上面的代码,self 强引用了 model, model 也强引用了doSomething 这个 block,而 block 的回调中又调用了self 的 name 属性,会导致 block 又强引用了 self,形成循环引用,导致 self 无法释放。

解决办法:

__weak typeof(self) weakSelf = self;
[self.model doSomething:^(NSNumber *id) {
    typeof(weakSelf) strongSelf = weakSelf;
    strongSelf.name = [NSString stringWithFormat:@"我的 id 是%@",id];
}];

或者

[self.model doSomething:^(NSNumber *id) {
    self.name = [NSString stringWithFormat:@"我的 id 是%@",id];
}];
self.model = nil

案例二:

@interface TestViewController ()
{
    NSInteger count;
}

@property (nonatomic, strong) TestModel *model;
@end


self.model = [[BHFeiModel alloc] init];
self.model.blockTest = ^{
    count = 9;
};

上面的代码乍一看,也没有问题, block 里没有出现 self 。但试验过你会发现,界面依然无法释放。

因为试用 {} 直接声明的,虽然不用 self 进行访问,但实质上和 @property 是一样的,还是会调用 self

因此,改用 @property 声明,然后通过 self 进行访问:

  self.model = [[BHFeiModel alloc] init];
    __weak typeof(self) weakSelf = self;
    self.model.blockTest = ^{
        typeof(weakSelf) strongSelf = weakSelf;
        strongSelf.imageCount = 9;
    };

这样便解决了循环引用导致界面无法释放的问题。

上一篇:Android values文件夹适配屏幕 下一篇:RecyclerView 上拉加载 PullToRefreshRecyclerView