Block - 循环引用

参考文档

注:建议阅读《循环引用的场景 & 处理》

  • 问题[※※※]:使用系统的某些block api(如UIView的block版本写动画时),是否也考虑引用循环问题?

情况分析

情况一:block是控制器的属性,如果block内部没有使用weakSelf将会造成内存泄露

self.testBlock = ^(){
    NSLog(@"%@",self.mapView);
};
self.testBlock();

情况二:把block内部抽出一个作为self的方法,当使用weakSelf调用这个方法,并且这个方法里有self的属性,block不会造成内存泄露

self.testBlock = ^(){
    [weakSelf test];
};

-(void)test
{
    NSLog(@"%@",self.mapView);
}

情况三:当block不是self的属性时,block内部使用self也不会造成内存泄露

TestBlock testBlock = ^(){
    NSLog(@"%@",self.mapView);
};
[self test:testBlock];

情况四:当使用类方法有block作为参数使用时,block内部使用self也不会造成内存泄露

[WDNetwork testBlock:^(id responsObject) {
    NSLog(@"%@",self.mapView);
}];

情况五:使用系统的某些block api(如UIView的block版本写动画时),是否也考虑引用循环问题?

所谓“引用循环”是指双向的强引用,所以那些“单向的强引用”(block 强引用 self )没有问题,比如这些:

[UIView animateWithDuration:duration animations:^{ 
    [self.superview layoutIfNeeded]; 
}];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    self.someProperty = xyz;
}];
[[NSNotificationCenter defaultCenter] addObserverForName:@"someNotification"
                                                  object:nil
                                                   queue:[NSOperationQueue mainQueue]
                                              usingBlock:^(NSNotification * notification) {
                                                   self.someProperty = xyz; 
                                              }];

这些情况不需要考虑“引用循环”。

但如果你使用一些参数中可能含有 ivar 的系统 api ,如 GCD 、NSNotificationCenter就要小心一点:比如GCD 内部如果引用了 self,而且 GCD 的其他参数是 ivar,则要考虑到循环引用:

__weak __typeof__(self) weakSelf = self;
dispatch_group_async(_operationsGroup, _operationsQueue, ^
{
    __typeof__(self) strongSelf = weakSelf;
    [strongSelf doSomething];
    [strongSelf doSomethingElse];
} );

类似的:

__weak __typeof__(self) weakSelf = self;
_observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"testKey"
                                                              object:nil
                                                               queue:nil
                                                          usingBlock:^(NSNotification *note) {
                                                              __typeof__(self) strongSelf = weakSelf;
                                                              [strongSelf dismissModalViewControllerAnimated:YES];
                                                          }];

self --> _observer --> block --> self 显然这也是一个循环引用。

ivar可以理解为类中的实例变量。 我们常用的属性@property可以理解为ivar+ setter + getter

你可能感兴趣的:(Block - 循环引用)