Retain Cycle

求一个点到任意两个点所在直线距离 C#代码公式 求点C(X0,Y0) 到点A(x1,y1)和点B(x2,y2)所在直线的距离 1.已知任意两个点,求这两个点所在直线 已知点A(x1,y1),点B(x2,y2) 设直线上另外任意一个点为(x,y) 那么 (x-x1)/(y-y1) = (x2-x1)/(y2-y1); 整理后得方程: (y2-y1)x + (x1-x2)y + (y1-... 阅读详情

在iOS4.0推出了Blocks這個語言特性後,到現在iOS都已經出到5.0了,所以我想Blocks應該可以被廣泛應用了
但現在iOS環境是從MRC(Manual Reference Counting) 走到ARC (Automatic Reference Counting)
在Reference Counting的環境中Runtime是無法自動解除Retain cycle的
而Blocks有很多隱性的retain的動作,很容易不小心的造成retain cycle。
而本篇的重點是點出三種會造成Retain Cycle的Anti-patterns,再來講一下怎麼解決。

在討論之前還是先大概重述一些概念,block當中是允許去使用外部的variable,但是local variable是會自動做retain的動作
例如

MyClass* foo = ….;
self.someBlock = ^
{
    [foo bar];
};

上面的foo在此block被copy到heap的時候,也會一起被自動retain,而這就是我說的很容易造成retain cycle的主因。


Anti Pattern 1
第一個例子我們先用大家很常用的Opne source library ASIHttpRequest當作一個範例
看看下面的例子,有發現任何問題嗎?

ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setCompletionBlock:^{
    NSString *responseString = [request responseString];
    NSData *responseData = [request responseData];
}];

這邊我們要首先要注意的點就是[request setCompletionBlock:…]這裡
很明顯的這邊的用途是要做一個event callback的用途,也就是說我給你一個block,當動作完成的時候callback我。這是一個典型的非同步的作法。
但由於如果你要把block拿來之後使用,你一定要呼叫[aBlock copy]的動作,此動作會把block從stack丟進heap。
因為在iOS的環境block也是一個object,此時這個block的retain count就會增加1
這時候根據定義,這個block中參照的request這個local變數就也會被retain起來。
所以request的retain count也會增加1。
但問題來了,一旦request完成任務,應當要被release的時候
卻會發現retain count始終無法歸零。

理由是 request <-> block 這兩個互相 retain 而無法正常釋放,這就是所謂的retain cycle了。


解決方法很簡單,看看ASIHttpRequest官網的文件也就是用__block來描述request

__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setCompletionBlock:^{
    NSString *responseString = [request responseString];
    NSData *responseData = [request responseData];
}];

通過block variable不會retain的特性,有點類似weak reference的作用,此時block就不會retain request
當然也就不會有retain cycle的問題。


Anti Pattern 2
Anti Pattern 1是在使用別人的library的時候容易出現的
Anti Pattern 2是在實作自己的class的時候容易出現
請看下面這段code

//MyClass.h
@property <nonatomic, copy=""> MyBlock onCompleteBlock;

//MyClass.c
self.onCompleteBlock = ^{
    [self doSomething];
}

我相信這邊大家已經馬上看出問題在哪裡了,其實Anti Pattern2算是Anti Pattern 1的特例,只是這邊使用的是特殊變數self

但有些時候我們更容易忽略的是在block中始用自己的member variable
例如

//MyClass.h
@interface MyClass : NSObject
{
    NSDate* lastModifed;
}

//MyClass.c
self.onCompleteBlock = ^{
    lastModifed = [[NSDate date] retain];
}

這時候就沒有那麼容易察覺了。根據定義,在使用block的時候,
如果我們使用到member variable,此時retain的不是lastModified指到的object 而是retain self。
所以造成的就是 self <-> block 互相 retain
跟anti pattern 1一樣的結果就是無法最終釋放記憶體。

這時候的解決方法也是一樣是拿出__block來用

//MyClass.c
__block MyClass* tempSelf = self;
self.onCompleteBlock = ^{
    tempSelf.lastModifed = [NSDate date];
}


Anti Pattern 3

繼續看下面的code

SettingsViewController* settingsViewController = [[[SettingsViewController alloc] init] autorelease];
settingsViewController.onUpdate = ^
{
    [self doUpdate];
}
self.settingsViewController = settingsViewController;


雖然這個Block中沒有直接使用到settingsViewController,感覺應該不會有retain cycle
但是因為 self. settingsViewController 而 settingsViewController.block 再來 block 里 [self doUpdate]
這就剛好繞了一圈,同樣會有retain cycle。

所以呢,還是要想一樣用anti pattern 2的解法去解決

//RootViewController.m
SettingsViewController* settingsViewController = [[[SettingsViewController alloc] init] autorelease];
__block RootViewController* tempSelf = self;
settingsViewController.onUpdate = ^
{
    [tempSelf doUpdate];
}
self.settingsViewController = settingsViewController;

在reference counting的環境裡,我建議要解決retain cycle的最好思維就是想清楚從屬關係
例如最後一個anti pattern 他們的從屬關係應該就是
RootViewController -> SettingsViewController -> block
如果block要用到SettingsViewController或是RootViewController,則就要使用weak reference (也就是__block)
在這樣的原則之下,就可以知道哪些要給他retain哪些不要了。

最後要補充一點就是上面的例子都是在MRC環境下當做範例,在MRC中__block variable在block中使用是不會retain的
但是ARC中__block則是會Retain的。
取而代之的是用__weak或是__unsafe_unretained來更精確的描述weak reference的目的
其中前者只能在iOS5之後可以使用,但是比較好 (該物件release之後,此pointer會自動設成nil)
而後者是ARC的環境下為了相容4.x的解決方案。
所以上面的範例中

__block MyClass* temp = …;    // MRC環境下使用
__weak MyClass* temp = …;    // ARC但只支援iOS5.0以上的版本
__unsafe_retained MyClass* temp = …;  //ARC且可以相容4.x以前的版本

 

ArcGIS Pro 3.0实战:5分钟搞定GDB批量转SHP的Python脚本(附常见错误修复) 本文详细介绍了在ArcGIS Pro 3.0中使用Python脚本将地理数据库(GDB)中的要素类批量转换为Shapefile(SHP)格式的实战方法。文章提供了从基础到增强的完整脚本,重点解决了中文路径报错、字段名截断和属性表乱码等常见问题,并分享了错误处理与编码修复技巧,帮助用户高效、准确地完成数据格式转换与交换。 阅读详情

相关推荐

别再只做游戏了!用虚幻引擎5(UE5)给你的工厂车间做个数字双胞胎(附数据对接教程)

本文详细介绍了如何利用虚幻引擎5(UE5)构建工业数字孪生系统,实现工厂车间的智能可视化。通过UE5的高质量渲染和实时数据处理能力,结合OPC UA和MQTT协议,打造高效的数据对接方案,提升异常识别和设备管理效率。文章还分享了模型优化、可视化设计及典型工业场景的实战案例,助力企业迈向工业4.0。

weixin_33738555的博客 206

GeekBand·iOS--Retain Cycle(引用循环)那些事

Retain Cycle:Retain Cycle是如何形成的呢?我们知道当一个父对象(主动方)持有子对象(被动方)时,子对象会随着父对象的消亡而消亡 但是假若两个对象互为父对象呢?会如何? 对,这样子,一个retain cycle就形成了,当然,互为父对象的引用都需要是强引用。 举个简单的例子: 就比如在一般的delegate情况下,一般都是子对象将delegate设为父对象,所以为

dark19940411的专栏 1967

用Pixel5玩转AOSP:从零开始定制Android13系统(含GMS集成方案)

本文提供了一份详尽的Pixel 5 AOSP定制指南,涵盖从环境搭建、源码下载、系统编译到刷机的完整流程。重点解决了原生AOSP缺失Google移动服务(GMS)的难题,分享了从官方镜像提取并集成GMS组件的实战方案,助你打造独一无二的Android 13系统。

sam99的博客 526

IOS内存泄露分析Retain Cycle的解决方法

一个使用Block语法的实例变量,在引用另一个实例变量的时候,经常会引起retain cycle。这个问题在使用ASIHTTPRequest的block语法的时候会时不时的碰到。这个问题困扰了我这个小白很久。终于有一天,在Advanced Mac OS X Programming上,看到了这个问题的解决方案。先用代码描述一下症状:#import typedef void (^ABlock)(void

dlmlzz09的专栏 1229

视觉-语言模型:BLIP与Flamingo如何理解图文?

视觉-语言模型:BLIP与Flamingo如何理解图文? ,人工智能,计算机视觉,大模型,AI,在当今人工智能飞速发展的时代,视觉 - 语言模型作为多模态领域的关键技术,正逐渐改变着我们与数字世界交互的方式。它们致力于打破图像与文本之间的模态壁垒,使计算机能够像人类一样,综合理解和处理视觉与语言信息。其中,BLIP 和 Flamingo 两款模型脱颖而出,以独特的架构和创新的训练方法,在图像描述生成、视觉问答、图文检索等任务中展现出卓越的性能。本文将深入剖析 BLIP 与 Flamingo 模型的工作原理。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 4万+

Codex 100个真实案例 - 用AI自动生成API测试用例(接口测试全覆盖)

API 测试是保障后端质量的关键环节,但手写测试用例既枯燥又容易遗漏。本案例将展示如何用 Codex 从 Swagger/OpenAPI 规范文档自动生成 pytest 测试用例——包括正常流程测试、边界值测试、异常参数测试、性能压力测试,还能自动生成 Mock 数据和精美的 HTML 测试报告。全程自然语言驱动,让 API 测试覆盖率从 0 飙到 90%+!

yueyeguzhuo的专栏 270

Captureing ‘self’ strongly in this block is likely to lead to a retain cycle Block的Retain Cycle的解决方法

一个使用Block语法的实例变量,在引用另一个实例变量的时候,经常会引起retain cycle。这个问题在使用ASIHTTPRequest的block语法的时候会时不时的碰到。这个问题困扰了我这个小白很久。终于有一天,在Advanced Mac OS X Programming上,看到了这个问题的解决方案。 先用代码描述一下症状: 1 2 3 4 5 6 7 8

hufeng825的专栏 1734

44、单级静态电流消耗最小化方法及功率优化比较器设计

本文探讨了单级静态电流消耗最小化方法及功率优化的多米诺逻辑比较器设计。通过分析类“AB”输入CMOS差分对电路,提出利用补偿电流源实现高低电流模式切换,提升运算放大器性能;结合VTCMOS与时钟门控技术,在90nm CMOS中设计低功耗比较器,并采用多米诺逻辑提高速度与能效。通过对比传统与改进型多米诺逻辑的静态功耗、动态功耗、延迟和PDP,验证了所提方案在高性能与低功耗方面的优势,适用于便携式设备等对能效要求严苛的应用场景。

pp12345的博客 121

iOS blocks - 三個會造成retain cycle的anti patterns

在iOS4.0推出了Blocks這個語言特性後到現在iOS都已經出到5.0了所以我想Blocks應該可以被廣泛應用了但現在iOS環境是從MRC(Manual Reference Counting) 走到ARC (Automatic Reference Counting)在Reference Counting的環境中Runtime是無法自動解除Retain cycle的而Blocks有很多隱性的re...

weixin_33991418的博客 148

小米15修复“NV损坏” 去除主板校验电阻步骤解析与图示

小米15系列将搭载骁龙8至尊版处理器,采用台积电3nm工艺。文章分析了手机出现"NV损坏"故障的表现及修复方法,包括通信异常、系统启动问题等典型症状,并介绍了去除主板校验电阻和刷写工程固件两种修复方案。重点讲解了去除主板电阻后刷写QCN文件的操作流程,强调在维修过程中需要结合分析与思考。适用于小米15系列特定机型(24129PN74G/I/C)的硬件修复。

小马哥的专栏 313

手机相机Tuning专项调优(一):基础流程与图像主观评价标准建立实战解析

本篇为手机相机系统“Tuning专项调优”系列的开篇,深入剖析了当前手机相机Tuning的基本流程与图像主观评价标准的构建方法。结合实际工程经验与最新业界案例,详细介绍ISP调优和3A控制中涉及的主观评价标准,如锐度、色彩饱和度、噪声感知等,并提出一套可工程化落地的标准制定与评测实践体系,帮助工程师有效提升图像品质。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 1933

探讨OC的内存管理 以及防止循环引用retain cycle 代理为什么用weak block为什么用copy

首先声明OC的内存管理机制:引用计数。当一个对象的引用计数为0时,这个对象就会被释放。铭记以上两点,我们开始来探讨。 换句话说,如果一个对象,没有强指针指向,就会被释放。举个很形象的例子,假如每一个对象都是一只狗,每一个强指针都是狗链子,狗链子的数量就是引用计数。那么情况就会变成这样:当一个狗没有被狗链子拴着的时候,它就跑了。哈哈~ 那么什么情况下又会造成循环引用呢?顾名思义,就是两个对象相互强引用

Se7en丶潇洒哥 的博客 2328

解读 2025《高质量数据集 质量评测规范》

《高质量数据集质量评测规范》为2025年数据质量评估提供标准化框架,适用于政府部门、AI企业、数据服务商等行业主体。规范以"说明文档-数据质量-模型应用"三维体系为核心:明确定义高质量数据集分类,细化各项指标要求(包括文档完整性、数据规范性、应用多样性等),并提供具体评分细则(百分制,90分达标)和计算方法。附录补充多模态数据处理细则,旨在建立可操作的质量评估标准,保障优质数据供给流通。

cdfunlove的博客 1881

警告:Block的Retain Cycle的解决方法

警告:Captureing ‘self’ strongly in this block is likely to lead to a retain cycle 一个使用Block语法的实例变量,在引用另一个实例变量的时候,经常会引起retain cycle。这个问题在使用ASIHTTPRequest的block语法的时候会时不时的碰到。这个问题困扰了我这个小白很久。终于有一天,在Advanc

taylor的专栏 1万+

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

关于block坑爹的retain Cycle

http://sealedace.com/blog/2014/01/23/block-retain-cycle/ 在进入正题之前,建议读一下船哥的文章——iOS中消息的传递机制。里面除了描述iOS中消息的传递机制,还提供了一些思路帮助大家正确选择某种传递方法来完成开发工作。而本篇文章的主题是跟block相关的。 我们知道在使用block时,必须避免出现retain cycl

fg313071405的专栏 777

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Block的Retain Cycle的解决方法

一个使用Block语法的实例变量,在引用另一个实例变量的时候,经常会引起retain cycle。这个问题在使ASIHTTPRequest的block语法的时候会时不时的碰到。这个问题困扰了我这个小白很久。终于有一天,在Advanced Mac OS X Programming上,看到了这个问题的解决方案。 先用代码描述一下症状: 1 2 3 4 5 6 7 8

SpeedBoy007的专栏 805

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

在使用block过程中,经常会遇到retain cycle的问题

SDWebImage库里的函数: - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(S

andy_jiangbin的专栏 710

Block的Retain Cycle的解决方法 (dealloc不掉用)

一个使用Block语法的实例变量,在引用另一个实例变量的时候,经常会引起retain cycle。这个问题在使用ASIHTTPRequest的block语法的时候会时不时的碰到。这个问题困扰了我这个小白很久。终于有一天,在Advanced Mac OS X Programming上,看到了这个问题的解决方案。 先用代码描述一下症状: 1 2 3 4 5 6 7 8

碧海蓝天的专栏 1755

解决block的retain cycle的警告问题

block retain cycle

青山流云的博客 516

正确使用Block避免Cycle Retain和Crash

http://tanqisen.github.io/blog/2013/04/19/gcd-block-cycle-retain/ 正确使用Block避免Cycle Retain和Crash APR 19TH, 2013 本文只介绍了MRC时的情况,有些细节不适用于ARC。比如MRC下__block不会增加引用计数,但ARC会,AR

sszTechnology的博客 492

capturing self strongly in this block is likely to lead to a retain cycle 警告解决

警告: capturing self strongly in this block is likely to lead to a retain cycle 意思是block会retain一次,所以使用前最好     __block ViewController *strongBlock = self; __block ViewController *strongBlock = s...

九天揽月 1万+

capturing self strongly in this block is likely to lead to a retain cycle

一个使用Block语法的实例变量,在引用另一个实例变量的时候,经常会引起retain cycle。capturing self strongly in this block is likely to lead to a retain cycle_items = [[NSMutableArray alloc] init]; _block = ^{ [_items ad...

jimmychan的博客 2599

RAC 中一个 retain cycle 问题

今天使用 RAC 注册通知时,遇到一个不是很明显的retain cycle问题,使用场景是在一个ViewController中注册一个通知,代码如下: 1 2 3 4 5 6 - (void)viewDidLoad { [super viewDidLoad]; [[[[NSNotificationCenter def...

weixin_34341117的博客 210
上一篇: Choose a destination with a supported architecture in order to run on this device.
下一篇: [UIColor colorWithRed: green: blue: alpha:] 失效问题
一秀
博客等级 码龄14年 1粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值