BLOCK循环引用

ubuntu20.4源码安装最新gcc(gcc V12.2) Ubuntu20.4自带的gcc为V9.4.0的版本,老版本的gcc存在不支持新版本C语言规范,在配置、编译、安装应用软件或工具时,可能存在不能正确安装的问题。(比如:libpqxx-7.7.4在配置时要求c++17版本的支持,但gcc V9.4.0版本不支持c++17)。因此本文介绍ubuntu20.4的系统下载最新gcc12.2版本源码,并进行本地编译、安装。本节内容包括gcc12.2的必备库安装和gcc12.2安装两部分内容组成。 阅读详情

循环引用的原因

众所周知,ARC下用block会产生循环引用的问题,造成泄露的原因是啥呢?

最简单的例子,如下面代码:

1
2
3
[self.teacher requestData:^(NSData *data) {
     self.name = @ "case" ;
}];

此种情况是最常见的循环引用导致的内存泄露了,在这里,self强引用了teacher, teacher又强引用了一个block,而该block在回调时又调用了self,会导致该block又强引用了self,造成了一个保留环,最终导致self无法释放。

self -> teacher -> block -> self

一般性的解决方案

1
2
3
4
5
__weak  typeof (self) weakSelf = self;
     [self.teacher requestData:^(NSData *data) {
         typeof (weakSelf) strongSelf = weakSelf;
        strongSelf.name = @ "case" ;
     }];

通过__weak的修饰,先把self弱引用(默认是强引用,实际上self是有个隐藏的__strong修饰的),然后在block回调里用weakSelf,这样就会打破保留环,从而避免了循环引用,如下:

self -> teacher -> block -> weakSelf

PS:一般会在block回调里再强引用一下weakSelf(typeof(weakSelf) strongSelf = weakSelf;),因为__weak修饰的都是存在栈内,可能随时会被系统释放,造成后面调用weakSelf时weakSelf可能已经是nil了,后面用weakSelf调用任何代码都是无效的。

通过demo证明哪些情况下有泄漏

虽然说用block时会产生循环引用,但并不是所有情况下都会有内存泄露的问题,看个demo。

先发demo地址:https://github.com/yuedong56/BlockRetainCycleDemo

  • 进入demo,有个Button,点击Button push到SecondViewController,

  • SecondViewController中有六种情况的Button,每点一个Button会触发一个block,

  • 点击返回,回到首页,如果执行了dealloc,证明SecondViewController正常释放,否则,证明内存泄露了。

01.png

下面只贴demo里的关键代码了,全的代码请自行下载demo,大家看下面的六种情况,是否会产生内存泄漏。

1
2
3
4
5
6
7
//情况一
- (void)case1 {
     NSLog(@ "case 1 Click" );
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
         self.name = @ "case 1" ;
     });
}
1
2
3
4
5
6
7
8
9
//情况二
- (void)case2 {
     NSLog(@ "case 2 Click" );
     __weak  typeof (self) weakSelf = self;
     [self.teacher requestData:^(NSData *data) {
         typeof (weakSelf) strongSelf = weakSelf;
        strongSelf.name = @ "case 2" ;
     }];
}
1
2
3
4
5
6
7
//情况三
- (void)case3 {
     NSLog(@ "case 3 Click" );
     [self.teacher requestData:^(NSData *data) {
         self.name = @ "case 3" ;
     }];
}
1
2
3
4
5
6
7
8
//情况四
- (void)case4 {
     NSLog(@ "case 4 Click" );
     [self.teacher requestData:^(NSData *data) {
         self.name = @ "case 4" ;
         self.teacher = nil;
     }];
}
1
2
3
4
5
6
7
8
//情况五
- (void)case5 {
     NSLog(@ "case 5 Click" );
     Teacher *t = [[Teacher alloc] init];
     [t requestData:^(NSData *data) {
         self.name = @ "case 5" ;
     }];
}
1
2
3
4
5
6
7
8
9
10
11
//情况六
- (void)case6 {
     NSLog(@ "case 6 Click" );
     [self.teacher callCase6BlackEvent];
     self.teacher.case6Block = ^(NSData *data) {
         self.name = @ "case 6" ;
         //下面两句代码任选其一
         self.teacher = nil;
//        self.teacher.case6Block = nil;
     };
}

分析

  • 情况一:执行了dealloc,不泄露,此情况虽然是block,但未形成保留环block -> self

  • 情况二:执行了dealloc,不泄露,此情况就是内存泄漏后的一般处理了 self ->teacher ->block ->strongSelf,后面那个strongSelf和原来的self并没有直接关系,因为strongSelf是通过weakSelf得来的,而weakSelf又没有强引用原来的self

  • 情况三:未执行dealloc,内存泄漏,此情况就是最典型的循环引用了,形成保留环无法释放,self ->teacher ->block ->self

  • 情况四:执行了dealloc,不泄露,虽然也是保留环,但通过最后一句,使self不再强引用teacher,打破了保留环

  • 情况五:执行了dealloc,不泄露,未形成保留环 t ->block ->self

  • 情况六:执行了dealloc,不泄露,最后两句代码任选其一即可防止内存泄漏,self.teacher 或者 case6Block 置为空都可以打破 retain cycle

PS: 虽然情况四、情况六的写法都可以防止内存泄漏,不过为了统一,个人建议最好还是按照普通写法即情况二的写法。

UE5实现物体高亮描边效果(含UE相关源码浅析) UE5实现物体高亮描边效果 阅读详情

相关推荐

ArduPilot + Gazebo + Mavros + QGC + 遥控器:从仿真到实机的自主轨迹控制实践

本文详细介绍了基于ArduPilot、Gazebo、Mavros和QGC的无人机自主轨迹控制全流程实践。从仿真环境搭建、多终端协同配置,到遥控器集成与自主圆形轨迹算法实现,提供了完整的代码示例和实机迁移要点,帮助开发者快速掌握无人机自主控制技术。

corn8的博客 940

ARC下的block导致的循环引用问题解析

引言 使用block已经有一段时间了,感觉自己了解的还行,但是几天前看到CocoaChina上一个关于block的小测试主题:【小测试】你真的知道blocks在Objective-C中是怎么工作的吗?,发现竟然做错了几道,才知道自己想当然的理解是错误的,所以抽时间学习了下,并且通过一些测试代码进行测试,产生这篇博客。 Block简介(copy一段) Block作为C语言的扩展,并不是高新技术

u013368288的专栏 683

INCA软件操作指南:手把手教你生成和解析DCM标定数据文件

本文详细介绍了INCA软件在汽车ECU开发中生成和解析DCM标定数据文件的全流程。从A2L文件导入到DCM文件生成,再到HEX文件导出,手把手教你掌握标定数据处理的实用技巧,包括参数标定、曲线标定和常见问题排查,帮助工程师提升工作效率。

weixin_29271053的博客 1052

iOS之ARC下的Block

【ARC的特性】   ARC下,所有NSObject类型指针,   1. 默认为__strong类型   2. 可以显示的指定为__weak类型,__weak类型指针在所指向对象销毁后会自动置为nil   3. __autorelesing类型用于inout参数类型   ARC下,当一个函数返回一个NSObject指针时,编译器会帮我们实现autorelease调用。

就要玩手游官方博客 596

VS2022离线环境下的NuGet包管理:从本地源到依赖项全解析

本文详细解析了在VS2022离线环境下如何高效管理NuGet包,包括搭建本地NuGet源的两种方案(本地文件夹源和私有NuGet服务器)、获取离线包的三大渠道以及依赖项处理的实战技巧。通过自动化脚本和依赖树分析工具,帮助开发者解决离线环境中的依赖项黑洞问题,提升开发效率。

5f4d3s2a1q的博客 1060

嵌入式通讯协议全解析:UART、I2C、SPI、CAN与Modbus实战指南

通讯协议是嵌入式系统设计的核心基础,也是面试与工程实践中避不开的关键环节。从串口UART的异步收发,到I2C总线寻址与SPI高速全双工传输,再到RS485差分长距离通信、CAN总线多主仲裁机制,以及工业领域事实标准的Modbus RTU协议,每一种技术都对应着特定的应用场景与设计权衡。理解协议背后的物理层原理、时序特征和工程坑点,才能真正解决设备间通信的选型、调试与健壮性问题。本文从基础概念出发,系统梳理各类嵌入式通讯协议的工作机制,并结合实际代码示例与对比表格,帮助开发者在面对面试问题或项目设计时,构建从

weixin_42520573的博客 275

iOS: ARC和非ARC下使用Block属性的问题

目录 1. Block的声明和调用 2. 循环引用问题   返回目录 1. Block的声明和线程安全 Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非ARC下返回Block)。 另一个需要注意的问题是关于线程安全,在声明Block属性时需要确

long458的专栏 1万+

OpenGL纹理贴图

OpenGL纹理1. 基本概念2. 纹理环绕方式3. 纹理过滤3.1 GL_NEAREST3.2 GL_LINEAR3.3 多级渐远纹理 (Mipmap)4. 纹理加载与创建4.1 纹理加载4.2 纹理创建4.3 纹理的使用 1. 基本概念 纹理是一个2D图片(甚至也有1D和3D的纹理),它可以用来表示物体的细节特征,希望绘制一个有足够多细节的物体,当然可以用足够多的顶点颜色来描述,但是无疑也增加了许多额外的开销;另一种办法就是使用纹理。 学习之前先展示一张实现的纹理图以更好理解纹理! 还是这张图为了将纹

牵LV小猪精的博客 8922

【iOS】——Block循环引用

此时self持有block,block弱引用self,弱引用会自动变为nil,强持有中断,所以不会引起循环引用。weakSelf被强引用了就不会自动释放,因为strongWeak只是一个临时变量,它的声明周期只在block内部,block执行完毕后,strongWeak就会释放,而弱引用weakSelf也会自动释放。在上面代码中,person对象强持有block对象,在block语法中,block对象又强持有person对象,此时达成互相强持有,谁也无法释法谁,造成循环引用。对person产生强引用。

m0_73974920的博客 1629

Stata中介效应分析实战:从sgmediation安装到Sobel检验结果解读

本文提供了Stata中进行中介效应分析的完整实战指南,重点介绍了第三方命令sgmediation的安装、配置与使用。通过详细案例演示了如何运用Sobel检验分析变量间的间接效应,并深入解读检验结果,帮助研究者厘清自变量影响因变量的具体路径。文章还探讨了Sobel检验的原理、优缺点及结果报告规范,是进行实证研究的实用参考。

weixin_29197051的博客 628

AIGC实战——多模态模型DALL.E 2

DALL.E 2 是 OpenAI 提出的一个大规模文本生成图像模型,可以根据文本提示生成各种风格的逼真图像。它通过将预训练模型 CLIP 与 GLIDE 中的扩散模型架构相结合完成任务。它还具有其他应用,例如通过文本提示编辑图像和提供给定图像的变体。虽然它也有一些局限性,例如不一致的文本渲染和属性绑定,但 DALL.E 2 是仍然一个非常强大的AI模型,推动了生成模型的发展。

盼小辉丶的博客 1万+

block的循环引用

前言 block的循环引用 Q: 为什么 block 会产生循环引用? 相互循环引用:如果当前block对当前对象的某一成员变量进行捕获的话,可能会对它产生强引用。根据block的变量捕获机制,如果block被拷贝到堆上,且捕获的是对象类型的auto变量,则会连同其所有权修饰符一起捕获,所以如果对象是__strong修饰,则block会对它产生强引用(如果block在栈上就不会强引用)。而当前block可能又由于当前对象对其有一个强引用,就产生了相互循环引用的问题; 总结 必须同时满足2个条件 1、 b

iOS随笔 3769

Python - 多页pdf 合称为一页

尝试使用 ReportLab 来重画 pdf,但探索起来有点麻烦。重要的是解决手头这个问题,所以就算方法蠢,但简单完事。以下生成结果,最有一页 pdf 可能会显示在第一页,手动编辑下 pdf 即可;或者你也可以修改代码逻辑来完善。打印ppt,一页占用A4纸比较浪费,想多页合成一个 A4大小;安装 fitz,单独安装 fitz 使用可能会报错。将 PDF 拆分为 图片来保存。

AI工程化、开源分享、文档翻译、代码笔记 1425

block循环引用

自从 block 横空出世,它本身就封装了一段代码当做变量,Apple 导入 block 语法之后就大幅改变了撰写 Objective-C 语言的方法。 block 是Cocoa/Cocoa Touch Framework 中的匿名函式(Anonymous Functions)的实作。所谓的匿名函式,就是一段 具有物件性质的程式码,这一段程式码可以当做函式执行,另一方面,又可以当做物件传递;因为可...

番薯大佬的专栏 1017

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

「iOS」————Block的循环引用

本文分析了Block循环引用的原因和解决方案。发生循环引用的原因大多是使用self时强持有了Block,而Block又强持有对象。我们来看看如何解决

2301_80253909的博客 790

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Block 循环引用浅谈

Block 的循环引用问题,想必使用过 Block,几乎都遇到过。今天CodeReview时,发现还存在循环引用的问题。故简单记录如下: 一、循环引用的原因 简单来说就是,【互相持有,造成内存不释放】。 如: self --持有--> block --持有--> self  形成了一个环,中间还可能穿插其他对象,反正最后形成了一个闭环,造成谁也不撒手,故内存永远不释放。

wwmusic的专栏 740

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

block的循环引用究竟是什么鬼?

block的循环引用

Friday_Holiday的专栏 2216

block-循环引用

block的循环引用,在日常开发中,我们常常遇到,但是可能部分新人还不太了解为何会循环引用,到底是如何循环引用理解得不够透彻,并且在ARC环境下只知道用__weakSelf去解决,但也不知道原因,现在我们来剖析一下,循环引用的的底层原理。看看下面一段常见的代码: 循环引用原因分析 #import <Foundation/Foundation.h> #import "RMPe...

信者的路 1067

你知道block循环引用怎么解决了吗?

✅作者简介:大家好我是瓜子三百克,一个非科班出身的技术程序员,还是喜欢在学习和开发中记录笔记的小白博主! 📃个人主页:瓜子三百克的主页 🔥系列专栏:OC语法 🤟格言:作为一个程序员都应该认识到,好的代码是初级工程师都可以理解的代码, 伟大的代码是可以被学习一年计算机专业的新生所理解。 💖如果觉得博主的文章还不错的话,请点赞👍+收藏⭐️+留言📝支持一下博主哦🤞 在使用block的时候,最需要注意的问题便是循环引用,这节主要讲解,block是如何产生的?碰到循环引用又该怎么解决。 文章目录一、循环引用的..

chenzimin_blog 915

Block循环引用详解

前言 作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS交流群:812157648,不管你是小白还是大牛欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长! 在项目中经常用到block,使用不当就很容易因为循环引用而造成内存泄漏。本文分析了block循环引用形成原因以及处理办法,如果有什么不对或者疑问请留言。 什么情况下block会造成循环引用 block为了保证代码块内部对象不被提前释放,会对block中的对象进行强引用,就相当于持有了其中的对象,而如.

iOSxiaodaidai的博客 701

iOS 中block的循环引用问题

开发中经常使用weakSelf和strongSelf来解决block的循环引用问题,但是是不是所有的block都会导致循环引用呢?显然不是的,那么怎么判断调用一个带有block方法时是否会造成循环引用呢,我们来分析一下。 首先我们来写一个含有block的类,并调用自己,然后在外部实现这个block,来测试什么情况会出现循环引用。 @interface ALDTestBlockModel () @...

浅浅的博客 1009

Block的循环引用解决方案理解

Block的循环引用原理和解决方法大家都比较熟悉,此处将结合上文的介绍,介绍一种不常用的解决Block循环引用的方法和一种借助Block参数解决该问题的方法。 Block循环引用原因:一个对象A有Block类型的属性,从而持有这个Block,如果Block的代码块中使用到这个对象A,或者仅仅是用用到A对象的属性,会使Block也持有A对象,导致两者互相持有,不能在作用域结束后正常释放。解决原理:对...

LIN1986LIN的专栏 1748

关于block的循环引用,你看我就够了!

开篇: 如果你之前看过我block的其他的文章,你会更容易今天这篇博客的一些更深的解释,每篇只有一个知识点,基本上把这些都看了,block基本不会有什么问题的,基本都是掌握了. block的源码解读之变量捕获机制(capture) 从源码、ARC、MRC带你理解block的三大类型 深入理解block的底层之copy 深入理解block的底层之对象类型的auto变量 深入理解__block修饰符的底层实现原理 循环引用: 在平时开发过程中,block是我们经常使用的功能,如果不多加注意就会造

Lucky_Deng的博客 1919

iOS Block 中 循环引用的解决

前言: 在iOS 中使用block 时 ,如果稍微不注意,则很容易 导致 循环引用 导致内存泄漏 二者都无法释放 。出现内存泄漏。 #import typedef void (^EOCNetworkFetcherCompletionHandler)(NSData *data); @protocol  EOCNetworkFetcherDelegate; @in

DeLongYangFor优快云的博客 995

iOS: Block的循环引用

Block的分类 首先我们来看一下有哪几种Block: 那么这3种Block分别在哪里体现出来呢?接下来,我们通过代码来看一下: void(^block)(void) = ^{ NSLog(@"123456"); }; block(); NSLog(@"%@",block); //万物皆对象,block也不例外 //运行代码,可以看到打印的内容是: //BlockDemo[...

weixin_33711647的博客 158

[iOS] 一次 Block 引起的循环引用的探索

本文主要涉及到了: (1) 使用 Block 添加通知时可能造成的循环引用问题; (2) 借助 dealloc 函数、 Leaks 工具和 Debug Memory Graph 工具分析循环引用的原因; (3) 页面 pop 后UINavigationController仍然保留页面引用的问题

wu_gq的博客 876
上一篇: 修改titleView的尺寸
下一篇: Masonry
网上的虫
博客等级 码龄11年 8粉丝 143原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值