美文网首页
block循环引用

block循环引用

作者: 7dfa9c18c1d1 | 来源:发表于2016-12-07 10:39 被阅读9次

我们都知道,在使用block的时候需要特别注意循环使用问题,比如在一个ClassA中:

@interface DDDViewController ()

@property (nonatomic, copy) void(^block)();

@property (nonatomic, strong) NSString *dog;

@end

@implementation DDDViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    self.dog = @"222";

    self.block = ^(){
            NSLog(@"%@",self.dog);
    };
    
    self.block();
}

-(void)dealloc
{
    NSLog(@"dealloc");
}
  • 上面这中情况下,就有循环问题发生,因为block本身是self的一个属性,self对block持有;而block会对它内部的变量进行持有,此时它内部就有self这个变量;导致的结果就是self和block互相持有,形成一个闭环;

  • 解决的方法,当然很简单,比如这样:

@interface DDDViewController ()

@property (nonatomic, copy) void(^block)();

@property (nonatomic, strong) NSString *dog;

@end

@implementation DDDViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    self.dog = @"222";
    
    __weak DDDViewController *weak = self;
    self.block = ^(){
        NSLog(@"====%@",weak.dog);
    };
    
    self.block();  
}

-(void)dealloc
{
    NSLog(@"dealloc");
}

使用weak修饰即可打破刚才的闭环。但是,比如有个这样的情景:
当前这个DDDViewController是被ClassA给Push出来的,然后执行下面的代码:

@interface DDDViewController ()

@property (nonatomic, copy) void(^block)();

@property (nonatomic, strong) NSString *dog;

@end

@implementation DDDViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    self.dog = @"222";
    
    __weak DDDViewController *weak = self;
    self.block = ^(){
         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"====%@",weak.dog);
        });
    };
    
    self.block();  
}

-(void)dealloc
{
    NSLog(@"dealloc");
}

大家认为打印是什么结果?

  • 其实有两种打印结果,分别是
  • 第一中结果是进去该界面后,在5s内退出
2016-12-07 10:22:00.444 CeShi[1180:47515] dealloc
2016-12-07 10:22:03.491 CeShi[1180:47515] ====(null)
  • 第二种结果是进去该界面后,在5s后退出
2016-12-07 10:22:12.285 CeShi[1180:47515] ====222
2016-12-07 10:22:14.161 CeShi[1180:47515] dealloc
  • 显然我们是希望看到结果2的,但是因为Vc被提前释放了,导致它的属性也被提前释放,然后我们去打印的时候,就是现实的null了,这个问题怎么解决?代码如下:
@interface DDDViewController ()

@property (nonatomic, copy) void(^block)();

@property (nonatomic, strong) NSString *dog;

@end

@implementation DDDViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    self.dog = @"222";
    
    __weak DDDViewController *weak = self;
    self.block = ^(){
        __strong typeof(self) strongSelf = weak;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"====%@",strongSelf.dog);
        });
    };
    
    self.block();
}

-(void)dealloc
{
    NSLog(@"dealloc");
}
  • 这样做,打印结果只有一种,即结果2。

所以我们平常写block的时候,并且需要在block中用到self的时候,可以采取这种方式

  • 思考:什么时候在block中用self,但是不需要修饰?
    比如这个:
[UIView animateWithDuration:0.2 animations:^{
    self.alpha = 1;
}];
  • 答案看到代码的时候就挺简单了:即block本身并不被self所持有,而是被别的对象所持有,此时block内使用self,就不需要被修饰

相关文章

网友评论

      本文标题:block循环引用

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