美文网首页
Block循环引用实例讲解

Block循环引用实例讲解

作者: 9fda4b908fad | 来源:发表于2017-02-27 15:42 被阅读87次

接上篇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

以上基本上就是开发中遇到比较多的循环引用的情况了,当然还要更加隐蔽的循环引用的情况存在,但是只要我们仔细一层一层的分析,还是能够发现的,多谢阅读.

相关文章

网友评论

      本文标题:Block循环引用实例讲解

      本文链接:https://www.haomeiwen.com/subject/piyzwttx.html