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

2023-10-24 07:00

本文主要是介绍iOS之Block报错:capturing self strongly in this block is likely to lead to a retain cycle,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原地址: http://blog.csdn.net/lvxiangan/article/details/50728577

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 修饰的变量在块中保存的是变量的地址。(其他为变量的值)

先用代码描述一下症状:

[objc]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. /* ViewController.h */     
  2. #import <UIKit/UIKit.h>    
  3. typedef void (^ABlock)(void); //定义一个简单的Block    
  4. @interface ViewController : UIViewController {    
  5.     NSMutableArray *_items;    
  6.     ABlock _block;    
  7. }    
  8.     
  9. @end    
  10.     
  11. /* ViewController.m */     
  12. #import "ViewController.h"    
  13. @implementation ViewController    
  14. - (void)viewDidLoad    
  15. {    
  16.     [super viewDidLoad];    
  17.     _items = [[NSMutableArray alloc] init];    
  18.     _block = ^{    
  19.         [_items addObject:@"Hello!"]; //_block引用了_items,导致retain cycle。    
  20.     };    
  21. }    
  22.     
  23. @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,然后用结构体语法访问实例变量。代码如下:

[objc]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. __block ViewController *blockSelf = self;    
  2. _block = ^{    
  3.     [blockSelf->_items addObject:@"Hello!"];    
  4. };    
这么修改之后 ,blockSelf是本地变量 ,是弱引用,因此在_block被retain的时候,并不会增加retain count,所以retain cycle就解除了,Xcode也不再出现警告了,问题解决。


例子2:
[objc]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. DoSomethingManager *manager = [[DoSomethingManager alloc] init];    
  2. manager.complete = ^{    
  3.     [manager otherAction];    
  4.     [manager release];    
  5. };    
retain cycle 就这么形成了,即使调用了release,manager也不会释放,因为manager和block相互持有了。为了解除retain cycle的话,我们可以这样写:
[objc]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. __block DoSomethingManager *manager = [[DoSomethingManager alloc] init];    
  2. __weak DoSomethingManager *weakmanager = manager;  
  3. manager.complete = ^{    
  4.     [weakmanager otherAction];    
  5. };    
终极解决方案:

[objc]  view plain  copy

  在CODE上查看代码片 派生到我的代码片
  1. - (IBAction)onTest:(id)sender  
  2. {  
  3.     BlockDemo *demo = [BlockDemo blockdemo];//[[BlockDemo alloc]init];  
  4.       
  5.     [demo setExecuteFinishedParam:^(BlockDemo * ademo) {  
  6.         if (ademo.resultCode == 200) {  
  7.             NSLog(@"call back ok.");  
  8.         }  
  9.     }];  
  10.       
  11.     [demo executeTest];  
  12. }  


这篇关于iOS之Block报错:capturing self strongly in this block is likely to lead to a retain cycle的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/273486

相关文章

qt5cored.dll报错怎么解决? 电脑qt5cored.dll文件丢失修复技巧

《qt5cored.dll报错怎么解决?电脑qt5cored.dll文件丢失修复技巧》在进行软件安装或运行程序时,有时会遇到由于找不到qt5core.dll,无法继续执行代码,这个问题可能是由于该文... 遇到qt5cored.dll文件错误时,可能会导致基于 Qt 开发的应用程序无法正常运行或启动。这种错

MySQL启动报错:InnoDB表空间丢失问题及解决方法

《MySQL启动报错:InnoDB表空间丢失问题及解决方法》在启动MySQL时,遇到了InnoDB:Tablespace5975wasnotfound,该错误表明MySQL在启动过程中无法找到指定的s... 目录mysql 启动报错:InnoDB 表空间丢失问题及解决方法错误分析解决方案1. 启用 inno

解决Java异常报错:java.nio.channels.UnresolvedAddressException问题

《解决Java异常报错:java.nio.channels.UnresolvedAddressException问题》:本文主要介绍解决Java异常报错:java.nio.channels.Unr... 目录异常含义可能出现的场景1. 错误的 IP 地址格式2. DNS 解析失败3. 未初始化的地址对象解决

Python报错ModuleNotFoundError的10种解决方案

《Python报错ModuleNotFoundError的10种解决方案》在Python开发中,ModuleNotFoundError是最常见的运行时错误之一,通常由模块路径配置错误、依赖缺失或命名冲... 目录一、常见错误场景与原因分析二、10种解决方案与代码示例1. 检查并安装缺失模块2. 动态添加模块

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I

idea报错java: 非法字符: ‘\ufeff‘的解决步骤以及说明

《idea报错java:非法字符:‘ufeff‘的解决步骤以及说明》:本文主要介绍idea报错java:非法字符:ufeff的解决步骤以及说明,文章详细解释了为什么在Java中会出现uf... 目录BOM是什么?1. BOM的作用2. 为什么会出现 \ufeff 错误?3. 如何解决 \ufeff 问题?最

解决Maven项目报错:failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.13.0的问题

《解决Maven项目报错:failedtoexecutegoalorg.apache.maven.plugins:maven-compiler-plugin:3.13.0的问题》这篇文章主要介... 目录Maven项目报错:failed to execute goal org.apache.maven.pl

电脑找不到mfc90u.dll文件怎么办? 系统报错mfc90u.dll丢失修复的5种方案

《电脑找不到mfc90u.dll文件怎么办?系统报错mfc90u.dll丢失修复的5种方案》在我们日常使用电脑的过程中,可能会遇到一些软件或系统错误,其中之一就是mfc90u.dll丢失,那么,mf... 在大部分情况下出现我们运行或安装软件,游戏出现提示丢失某些DLL文件或OCX文件的原因可能是原始安装包

电脑显示mfc100u.dll丢失怎么办?系统报错mfc90u.dll丢失5种修复方案

《电脑显示mfc100u.dll丢失怎么办?系统报错mfc90u.dll丢失5种修复方案》最近有不少兄弟反映,电脑突然弹出“mfc100u.dll已加载,但找不到入口点”的错误提示,导致一些程序无法正... 在计算机使用过程中,我们经常会遇到一些错误提示,其中最常见的就是“找不到指定的模块”或“缺少某个DL

解决IDEA报错:编码GBK的不可映射字符问题

《解决IDEA报错:编码GBK的不可映射字符问题》:本文主要介绍解决IDEA报错:编码GBK的不可映射字符问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录IDEA报错:编码GBK的不可映射字符终端软件问题描述原因分析解决方案方法1:将命令改为方法2:右下jav