虽然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;
};
这样便解决了循环引用导致界面无法释放的问题。
网友评论