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

相关文章

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

Jenkins 插件 地址证书报错问题解决思路

问题提示摘要: SunCertPathBuilderException: unable to find valid certification path to requested target...... 网上很多的解决方式是更新站点的地址,我这里修改了一个日本的地址(清华镜像也好),其实发现是解决不了上述的报错问题的,其实,最终拉去插件的时候,会提示证书的问题,几经周折找到了其中一遍博文

【Python报错已解决】AttributeError: ‘list‘ object has no attribute ‘text‘

🎬 鸽芷咕:个人主页  🔥 个人专栏: 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路 二、解决方法2.1 方法一:检查属性名2.2 步骤二:访问列表元素的属性 三、其他解决方法四、总结 前言 在Python编程中,属性错误(At

DBeaver 连接 MySQL 报错 Public Key Retrieval is not allowed

DBeaver 连接 MySQL 报错 Public Key Retrieval is not allowed 文章目录 DBeaver 连接 MySQL 报错 Public Key Retrieval is not allowed问题解决办法 问题 使用 DBeaver 连接 MySQL 数据库的时候, 一直报错下面的错误 Public Key Retrieval is

vue 父组件调用子组件的方法报错,“TypeError: Cannot read property ‘subDialogRef‘ of undefined“

vue 父组件调用子组件的方法报错,“TypeError: Cannot read property ‘subDialogRef’ of undefined” 最近用vue做的一个界面,引入了一个子组件,在父组件中调用子组件的方法时,报错提示: [Vue warn]: Error in v-on handler: “TypeError: Cannot read property ‘methods

Vue3上传图片报错:Current request is not a multipart request

当你看到错误 "Current request is not a multipart request" 时,这通常意味着你的服务器或后端代码期望接收一个 multipart/form-data 类型的请求,但实际上并没有收到这样的请求。在使用 <el-upload> 组件时,如果你已经设置了 http-request 属性来自定义上传行为,并且遇到了这个错误,可能是因为你在发送请求时没有正确地设置

[Linux Kernel Block Layer第一篇] block layer架构设计

目录 1. single queue架构 2. multi-queue架构(blk-mq)  3. 问题 随着SSD快速存储设备的发展,内核社区越发发现,存储的性能瓶颈从硬件存储设备转移到了内核block layer,主要因为当时的内核block layer是single hw queue的架构,导致cpu锁竞争问题严重,本文先提纲挈领的介绍内核block layer的架构演进,然

QT 编译报错:C3861: ‘tr‘ identifier not found

问题: QT 编译报错:C3861: ‘tr’ identifier not found 原因 使用tr的地方所在的类没有继承自 QObject 类 或者在不在某一类中, 解决方案 就直接用类名引用 :QObject::tr( )

笔记本电脑开机报错故障的原因及解决办法

笔记本电脑开机报错故障是指笔记本电脑开机自检时或启动操作系统前停止启动,在显示屏 出现一些错误提示的故障。   笔记本电脑开机报错故障的原因及解决办法   造成此类故障的原因一般是笔记本电脑在启动自检时,检测到硬件设备不能正常工作或在自 检通过后从硬盘启动时,出现硬盘的分区表损坏、硬盘主引导记录损坏、硬盘分区结束标志丢失 等故障,笔记本电脑出现相应的故障提示。   维修此类故障时