iOS之Block报错:capturing self strongly in this block is likely to lead to a retain cycle

我们经常在block使用中碰到:capturing self strongly in this block is likely to lead to a retain cycle。

重要法则:
block对于其变量都会形成强引用(retain),对于self也会形成强引用(retain),而如果self本身对block也是强引用的话,就会形成 强引用 循环,无法释放——造成内存泄露。
1)self会对自己的属性或函数进行持有。
2)block主函数体,用到了self所拥有的任何东西(self、self.属性、[self 函数] ),block就会对self进行持有。
3)如果1、2情况同时存在,就会出现retain cycle问题。因为1)很难做出改变,所以解决方法是对2进行改进。

如何避免?
1、简单判断:我一般重写dealloc方法,查看dealloc方法是否调用来判断是否有循环引用。
2、深层分析:根据上面法则来分析代码。


1、被block引用的变量都会被自动retain一次 ,这样的话至少可以保证我们的调用是有效的。因为 block中的retain是隐式的 ,所以极易出现retain cycle的问题。
2、retain cycle ,翻译成中文大概叫保留环吧。比如A和B两个对象,A持有B,B同时也持有A,A只有B释放之后才有可能释放,同样B只有A释放后才可能释放,当双方都在等待对方释放的时候, retain cycle就形成了,结果是,两个对象都永远不会被释放,最终内存泄露。
3、__strong : 赋值给这个变量的对象会自动被retain一次, 如果在block中引用它,block也会retain它一次
4、__unsafe_unretained : 赋值给这个变量不会被retain,也就是说被他修饰的变量的存在不能保证持有对象的可靠性,它可能已经被释放了,而且留下了一个不安全的指针。不会被block retain。 
5、__weak :类似于__unsafe_unretained,只是如果所持有的对象被释放后,变量会自动被设置为nil,这样更安全些,不过只在IOS5.0以上的系统支持,同样不会被block retain。
6、__block:  表示 这个变量值能在block中被修改 (值修改,而不是修改对象中的某一个属性,可以理解为修改指针的指向)。 会被自动retain
被 __block 修饰的变量在块中保存的是变量的地址。(其他为变量的值)



使用__weak打破循环的方法只在ARC下才有效,在MRC下应该使用__block

先用代码描述一下症状:
/* ViewController.h */   
#import <UIKit/UIKit.h>  
typedef void (^ABlock)(void); //定义一个简单的Block  
@interface ViewController : UIViewController {  
    
    // self的属性
    NSMutableArray *_items;

    // 1、self的属性,换句话说,self持有block,即self对block具有强引用
    ABlock _block; 
}  
  
@end  
  
/* ViewController.m */   
#import "ViewController.h"  
@implementation ViewController  
- (void)viewDidLoad  
{  
    [super viewDidLoad];  
    _items = [[NSMutableArray alloc] init];  

    _block = ^{  
       
        // 2、_block内部用到了self的属性_items,换句话说,_block持有了self,导致retain cycle。  
        // 因为只要 block中用到了对象的属性或者函数,block就会持有该对象而不是该对象中的某个属性或者函数。
        [_items addObject:@"Hello!"]; 

    };  
}
@end
Xcode在编译以上程序的时候会给出一个警告:Captureing ‘self’ strongly in this block is likely to lead to a retain cycle。
原因: _items实际上是self->items。_block对象在创建的时候会被retain一次,因此会导致self也被retain一次。这样就形成了一个retain cycle。
解决方法: 创建一个本地变量blockSelf,指向self,然后用结构体语法访问实例变量。代码如下:
__block ViewController *blockSelf = self;  
_block = ^{  
    [blockSelf->_items addObject:@"Hello!"];  
};  
这么修改之后,blockSelf是本地变量,是弱引用,因此在_block被retain的时候,并不会增加retain count,所以retain cycle就解除了,Xcode也不再出现警告了,问题解决。

例子2:
DoSomethingManager *manager = [[DoSomethingManager alloc] init];  
manager.complete = ^{  
    [manager otherAction];  
    [manager release];  
};  
retain cycle 就这么形成了, 即使调用了release,manager也不会释放,因为manager和block相互持有了。 为了解除retain cycle的话,我们可以这样写:
__block DoSomethingManager *manager = [[DoSomethingManager alloc] init];  
__weak DoSomethingManager *weakmanager = manager;
manager.complete = ^{  
    [weakmanager otherAction];  
};  

终极解决方案:

- (IBAction)onTest:(id)sender  
{  
    BlockDemo *demo = [BlockDemo blockdemo];//[[BlockDemo alloc]init];  
      
    [demo setExecuteFinishedParam:^(BlockDemo * ademo) {  // 2、自动回调:把demo传入block函数主体,作为函数主体的局部变量
        // 3、在这里使用demo,不受外界影响
        if (ademo.resultCode == 200) {
            NSLog(@"call back ok.");  
        }  
    }];  
      
    // 1、先执行自定义XX操作,并把demo作为block参数,回调block
    [demo executeTest]; 
}  

自己写block时,如果是回调,比较喜欢把自身当作参数传到block中。这样其实是编译器给我们做了弱引用。因此不会产生循环引用。


  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Introduction to Visual Computing: Core Concepts in Computer Vision, Graphics, and Image Processing covers the fundamental concepts of visual computing. Whereas past books have treated these concepts within the context of specific fields such as computer graphics, computer vision or image processing, this book offers a unified view of these core concepts, thereby providing a unified treatment of computational and mathematical methods for creating, capturing, analyzing and manipulating visual data (e.g. 2D images, 3D models). Fundamentals covered in the book include convolution, Fourier transform, filters, geometric transformations, epipolar geometry, 3D reconstruction, color and the image synthesis pipeline. The book is organized in four parts. The first part provides an exposure to different kinds of visual data (e.g. 2D images, videos and 3D geometry) and the core mathematical techniques that are required for their processing (e.g. interpolation and linear regression.) The second part of the book on Image Based Visual Computing deals with several fundamental techniques to process 2D images (e.g. convolution, spectral analysis and feature detection) and corresponds to the low level retinal image processing that happens in the eye in the human visual system pathway. The next part of the book on Geometric Visual Computing deals with the fundamental techniques used to combine the geometric information from multiple eyes creating a 3D interpretation of the object and world around us (e.g. transformations, projective and epipolar geometry, and 3D reconstruction). This corresponds to the higher level processing that happens in the brain combining information from both the eyes thereby helping us to navigate through the 3D world around us. The last two parts of the book cover Radiometric Visual Computing and Visual Content Synthesis. These parts focus on the fundamental techniques for processing information arising from the interaction of light with objects around us, as well as the fundamentals of creating virtual computer generated worlds that mimic all the processing presented in the prior sections. The book is written for a 16 week long semester course and can be used for both undergraduate and graduate teaching, as well as a reference for professionals.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值