[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 ...
随机推荐
- Ajax实现在textbox中输入内容,动态从数据库中模糊查询显示到下拉框中
功能:在textbox中输入内容,动态从数据库模糊查询显示到下拉框中,以供选择 1.建立一aspx页面,html代码 <HTML> <HEAD> <title>We ...
- Moon.Orm 5.0 (MQL版)
Moon.Orm 5.0 (MQL版) 实战实例Moon.Orm 5.0 革命性的设计 打造最便捷的异步分页技术(提供下载) 摘要: 一.建一个项目(以WebForm为例)配置文件配置(注意您自己的路 ...
- windows下mysql备份、还原,使用mysqldump
直接备份 mysqldump -u用户名 -p密码 -h 192.168.1.15 -c --default-character-set=utf8 数据库名>xxx.sql 使用gz ...
- modalDialog的使用,图片切换,点击图片时打开一个窗体,并显示信息
//主窗体 //与open的区别:1.参数二是传递的参数 2.属性设置格式:属性=属性值; 3.dialogHeight与dialogWidth没有单位,即需要自己加上px //window.show ...
- visual c++ 动态链接库调用总结
由于每次使用动态链接库的时候都要重新去查资料,查调用方式,有些烦躁,本人抽点时间在此做个总结,希望可以对需要的朋友有所帮助. 1,显式加载方式加载动态链接库 简单易懂,随掉随用 (1) ...
- ASP.NET WebApi 入门
今天参照微软官方(http://www.asp.net)学习了WebApi,在这里摘录如下: 前言 HTTP 不只是为了生成 web 页面.它也是一个强大的平台,可以建设公开服务和数据的 Api.HT ...
- 使用Strust2框架写HelloWorld
使用Strust2框架写HelloWorld 一.创建JavaWeb项目 二.搭建Stust2 FrameWork开发环境 三步完成Struts2 FrameWork开发环境的搭建 1.加入搭建Str ...
- Struts2的拦截器
拦截器的作用: 拦截器可以动态地拦截发送到指定Action的请求,通过拦截器机制,可以载Action执行的前后插入某些代码,植入我们的逻辑思维. 拦截器的实现原理: 拦截器通过代理的方式来调用,通过动 ...
- sendrose【SPFA】
之前看到一题需要并查集+SPFA,然后就特别囧的发现自己SPFA这个历史遗留问题已经不知道怎么打了╮(╯▽╰)╭ 就果断挑了一题特别裸的SPFA赶紧搞搞掉,顺便自己乱YY下学SPFA的笔记,免得自己下 ...
- webx学习1
webx的配置 如果想在web项目中使用webx框架,需要在web-inf/web.xml文件中进行相关的配置. 1.初始化spring容器 初始化spring容器- /web-inf/web.xml ...