[ios2]警告:Block的Retain Cycle的解决方法 【转】
- <span style="background-color: rgb(248, 248, 248); font-family: 'PT Sans', Geogia, Baskerville, 'Hiragino Sans GB', serif; ">警告:Captureing ‘self’ strongly in this block is likely to lead to a retain cycle</span>
一个使用Block语法的实例变量,在引用另一个实例变量的时候,经常会引起retain cycle。这个问题在使用ASIHTTPRequest的block语法的时候会时不时的碰到。这个问题困扰了我这个小白很久。终于有一天,在 Advanced Mac OS X Programming上,看到了这个问题的解决方案。
先用代码描述一下症状:
- <span style="font-size:18px;">/* ViewController.h */
- #import <UIKit/UIKit.h>
- typedef void (^ABlock)(void); //定义一个简单的Block
- @interface ViewController : UIViewController {
- NSMutableArray *_items;
- ABlock _block;
- }
- @end
- /* ViewController.m */
- #import "ViewController.h"
- @implementation ViewController
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- // Do any additional setup after loading the view, typically from a nib.
- _items = [[NSMutableArray alloc] init];
- _block = ^{
- [_items addObject:@"Hello!"]; //_block引用了_items,导致retain cycle。
- };
- }
- @end</span>
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也不再出现警告了,问题解决。
注:本文并非原创,详情请参阅Advanced Mac OS X Programming,第92页“Block Retain Cycles”。
n manual reference counting mode, __block id x; has the effect of not retaining x. In ARC mode, __block id x; defaults to retaining x (just like all other values). To get the manual reference counting mode behavior under ARC, you could use __unsafe_unretained __block id x;. As the name __unsafe_unretained implies, however, having a non-retained variable is dangerous (because it can dangle) and is therefore discouraged. Two better options are to either use __weak (if you don’t need to support iOS 4 or OS X v10.6), or set the __block value to nil to break the retain cycle.
The following code fragment illustrates this issue using a pattern that is sometimes used in manual reference counting.
MyViewController *myController = [[MyViewController alloc] init…]; |
// ... |
myController.completionHandler = ^(NSInteger result) {
|
[myController dismissViewControllerAnimated:YES completion:nil]; |
}; |
[self presentViewController:myController animated:YES completion:^{
|
[myController release]; |
}]; |
As described, instead, you can use a __block qualifier and set the myController variable to nil in the completion handler:
MyViewController * __block myController = [[MyViewController alloc] init…]; |
// ... |
myController.completionHandler = ^(NSInteger result) {
|
[myController dismissViewControllerAnimated:YES completion:nil]; |
myController = nil; |
}; |
Alternatively, you can use a temporary __weak variable. The following example illustrates a simple implementation:
MyViewController *myController = [[MyViewController alloc] init…]; |
// ... |
MyViewController * __weak weakMyViewController = myController; |
myController.completionHandler = ^(NSInteger result) {
|
[weakMyViewController dismissViewControllerAnimated:YES completion:nil]; |
}; |
For non-trivial cycles, however, you should use:
MyViewController *myController = [[MyViewController alloc] init…]; |
// ... |
MyViewController * __weak weakMyController = myController; |
myController.completionHandler = ^(NSInteger result) {
|
MyViewController *strongMyController = weakMyController; |
if (strongMyController) {
|
// ... |
[strongMyController dismissViewControllerAnimated:YES completion:nil]; |
// ... |
} |
else {
|
// Probably nothing... |
} |
}; |
[ios2]警告:Block的Retain Cycle的解决方法 【转】的更多相关文章
- Block的Retain Cycle的解决方法
一个使用Block语法的实例变量,在引用另一个实例变量的时候,经常会引起retain cycle.这个问题在使ASIHTTPRequest的block语法的时候会时不时的碰到.这个问题困扰了我这个小白 ...
- elasticsearch报错expected <block end>, but found BlockMappingStart解决方法
我用的是elasticsearch2.4.0,在修改完配置文件就出现类似格式 expected <block end>, but found BlockMappingStart...... ...
- 处理Block中的self问题(Capturing 'self' strongly in this block is likely to lead to a retain cycle)
警告:ARC Retain Cycle Capturing 'self' strongly in this block is likely to lead to a retain cycle 代码: ...
- div之间有间隙以及img和div之间有间隙的原因及解决方法
原因: div 中 存在 img标签,由于img标签的 display:inline-block 属性. display:inline-block布局的元素在chrome下会出现几像素的间隙,原因是因 ...
- Block代替delegate,尽量使用block,对于有大量的delegate方法才考虑使用protocol实现.
Block代替delegate,尽量使用block,对于有大量的delegate方法才考虑使用protocol实现. 1.Block语法总结及示例如下: //1.普通代码块方式bloc ...
- 关于找不到指定的模块,异常来自HRESULT:0x8007007E的解决方法
上午从公司前辈那里拷贝到的ASP.NET代码,在自己机器上部署的时候发现问题,直接报错,找不到指定的模块,异常来自HRESULT:0x8007007E.并且一大堆警告. 在网上百度很多解决方法,归纳如 ...
- img和div之间有间隙的原因及解决方法
div 中 存在 img标签,由于img标签的 display:inline-block 属性. #####display:inline-block布局的元素在chrome下会出现几像素的间隙,原因是 ...
- xcode arc 下使用 block警告 Capturing [an object] strongly in this block is likely to lead to a retain cycle” in ARC-enabled code
xcode arc 下使用 block警告 Capturing [an object] strongly in this block is likely to lead to a retain cyc ...
- 在block函数中规避错误信息 "capturing self strongly in this block is likely to lead to a retain cycle”
以形如 _fontValueChangedBlock = ^(){ [self.fontSmallButton addTarget:self action:@selector(btnFontSmall ...
随机推荐
- lucent检索技术之创建索引:使用POI读取txt/word/excel/ppt/pdf内容
在使用lucent检索文档时,必须先为各文档创建索引.索引的创建即读出文档信息(如文档名称.上传时间.文档内容等),然后再经过分词建索引写入到索引文件里.这里主要是总结下读取各类文档内容这一步. 一. ...
- 关于 js 中的 call 和 apply使用理解
关于 js 中的 call 和 apply使用理解 在学习新的东西时候,碰到以前看过而又不理解,或则记忆不深的地方不妨回头看看书里知识点,有助于加深理解.正所谓--温故而知新. 废话不多说,直接上代码 ...
- 1951: [Sdoi2010]古文字猪
1951: [Sdoi2010]古代猪文 链接:Click Here~ 题目: 一道非常好的组合数学题.!!.题目非常长.只是就以下几段话实用. iPig认为仅仅要符合文献,每一种能整除N的k都是有可 ...
- Apworks到底是什么?
Apworks到底是什么? 简介 Apworks是一款基于Microsoft .NET的面向领域驱动的企业级应用程序开发框架,它适用于以领域模型为核心的企业级系统的开发和集成.Apworks不仅能够很 ...
- WisDom .net开发框架设计 2
随笔- 10 文章- 0 评论- 57 WisDom .net开发框架设计 (二) WisDom .net 权限设计 1.前言 几乎在所有的管理的系统,都离不开用户,角色,权 ...
- 【学习笔记】《JavaScript DOM 编程艺术》 ——总结
一.要点阐述 1,程序设计语言分为解释型和编译型两大类,JS属于解释型,在Web浏览器中一边解释一边执行. 2,"//"注释单行,"/*...*/"注释多行.反 ...
- visual studio快捷键总结
熟练操作vs的快捷键,可以有效地提高开发效率,下面将vs 2008与vs 2010的快捷键进行了总结,结果如下表: 注:vs 2010与vs 2008的快捷键基本相同. 编辑: CTRL + M, ...
- silverlight中datagrid数据到处excel
首先新建一个DataGrdiExtensions类,代码为: public static class DataGridExtensions { /// <summary> /// 导出dg ...
- soket.io.js + angular.js + express.js(node.js)
soket.io.js + angular.js + express.js(node.js) 今天搭建个soket.io.js + angular.js + express.js的环境, 采坑无数,特 ...
- 基于SUSE Linux做NFS文件挂载
linux文件挂载其实和windows文件共享原理差不多,由主机配置一个共享目录,客户端机器可以通过网络访问该共享目录. 下面以SUSE11为例子,简要描述下NFS文件挂载过程: 一.主机端(主机IP ...