Block循环引用实例讲解
2017-02-27 本文已影响87人
9fda4b908fad
接上篇block实现原理探究,本篇为上篇的补充篇,如果有兴趣,可以看看上篇的内容(链接在这里),两篇内容的偏向有所不同,所以不用担心,会影响到本篇阅读.
block循环引用在日常开发过程中,是肯定会遇到的问题,除非你不使用block.但是可能有部分的小伙伴对这个问题没有深入的研究过,在这里,我希望抛砖引玉,希望能帮助到你.如果文中有不对的地方,欢迎指正.
下面开始进入正题:
下面以三种情形的方式分析,以下代码全部循环引用的全部代码
@interface TestViewController ()
@property (nonatomic,copy) void (^testBlock)();
@property (nonatomic,strong) Person *person;
@end
@implementation TestViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor purpleColor];
//情况一
[self situationOne];
//情况二
// [self situationTwo];
//情况二
// [self situationThree];
}
- (void)situationOne
{
self.testBlock = ^{
NSLog(@"%@",self);
};
}
- (void)situationTwo
{
Person *p = [[Person alloc] init];
p.block = ^{
NSLog(@"%@",p);
};
}
- (void)situationThree
{
Person *p = [[Person alloc] init];
p.block = ^{
NSLog(@"%@",self);
};
self.person = p;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self dismissViewControllerAnimated:true completion:nil];
}
-(void)dealloc
{
NSLog(@"%s:The CurrentViewController is Dealloc",__func__);
}
@end
另外一个Person文件
@interface Person : NSObject
@property (nonatomic,copy) void (^block)();
@end
-
情形一:
这种情况我们可以看到VC(这里就是self)
当中有个testBlock,而testBlock中又引用了VC,这两者之间就形成一个引用环,导致VC没有办法释放. -
情形二:
这种情况和情形一类似,Person和block之间产生了一个引用环,导致Person没有办法释放
这里需要解释一点的是,有些小伙伴认为这里没有循环引用,因为他们觉得没有对象对person强引用,出了这个方法自然就被销毁了,其实这个理解是有误的,block对person的引用不应该被忽略
解决上面两种情况循环引用的办法一样,就是让block里面引用外部的变量的形式变成弱引用,使引用环没有办法形成,以情形一为例,代码应该改为:
__weak typeof(self) _self = self;
self.testBlock = ^{
NSLog(@"%@",_self);
};
- 情形三:
这种情况牵扯到几个对象,而且编译器不会提示你有循环引用存在的问题存在,所以相对上面情况比较隐蔽一点,其实认真分析以下也不难发现 : person引用block,block引用VC(这里指的是self)
,VC当中又引用了person,一个引用环就产生了,解决的办法也很简单,只要block中的那一环断掉就行了,即:
Person *p = [[Person alloc] init];
__weak typeof(self) _self = self;
p.block = ^{
NSLog(@"%@",_self);
};
self.person = p;
注: 以上代码在ARC环境下适用,如果在MRC的环境下,你需要将 __weak换成 __block
以上基本上就是开发中遇到比较多的循环引用的情况了,当然还要更加隐蔽的循环引用的情况存在,但是只要我们仔细一层一层的分析,还是能够发现的,多谢阅读.