目标 C:块案例中的内存管理
Posted
技术标签:
【中文标题】目标 C:块案例中的内存管理【英文标题】:Objective C: Memory management in Block cases 【发布时间】:2011-06-29 17:18:19 【问题描述】:我想知道我是否使用如下代码所示的块
__block Loader *loader = [[Loader alloc]initWithResourcePath:self.resourcePath];
[loader setCompletionHandler:^(NSArray *anArray)
self.answerArray=anArray;
[self reloadData];
];
[loader getObjects];
我的问题是关于内存管理的。分析器告诉我有一个潜在的泄漏(因为我为我的加载器做了一个 alloc/init)。我怎样才能阻止这里的泄漏?我试图在最后释放加载程序,但这会导致我的应用程序停止运行。任何建议在这里表示赞赏
【问题讨论】:
停止运行如何?你得到什么错误?很有可能它会帮助您找到问题的原因。 您将 loader 声明为 __block 有什么原因吗? 【参考方案1】:几个问题:
没有理由将loader
声明为__block
;您没有在块中重新分配,因此,__block
毫无意义。
泄漏是因为你alloc/init
加载器,但从未释放它
不要命名方法getSomething
; get
前缀是为通过引用返回内容的方法保留的。就叫它objects
。如果它应该触发负载,则调用它load
或performLoad
。
如果是异步的,那么getObjects
是没有意义的。如果是同步的,那么完成块是没有意义的。
如果要同步使用loader
,则release
在方法的末尾。如果是asynchronous
,那么完成块可以释放它。请注意,在这种情况下使用__block
仍然没有意义;虽然在完成块中引用 loader
将创建一个保留周期,但当您明确 Block_release() 块中的 loader
时它将被破坏(因为您必须已经完成了 Block_copy()
设置完成处理程序时,如果它首先要异步使用)。
【讨论】:
我在 ASIHTTPRequest (allseeing-i.com/ASIHTTPRequest/How-to-use) 网站上读到,在声明请求时使用 __block 限定符很重要。但是我可以说这个例子是相关的,因为他们实际上在块中使用了 request 吗? 是的,由于我上面描述的原因,只有他们选择在连接完成或出错时不释放块(即一旦不再调用块),从而创建一个循环。我选择使用在对象生命周期中自动中断循环的模式。【参考方案2】:如果你打算在调用你的块的函数之外使用loader
,你很有可能需要将它存储在控制器的 ivar 中(我猜它是一个控制器,但我不知道什么样的类拥有您显示的代码)。完成此操作后,您可以在 dealloc
中发布它。
原因是loader
应该存在于多个方法和运行循环循环中,因此局部变量不会这样做。
否则,一旦你完成它,只需在块的末尾释放它。
如果您觉得这不正确,那么可能需要更多代码。
【讨论】:
【参考方案3】:我将做一些假设: 1) 完成处理程序(块)由方法 getObjects 使用。 2) getObjects 是异步的(它会立即返回给调用者,尽管它会继续处理)。
根据这些假设,您无法在发送 getObjects 后发送 release,因为 getObjects 仍在使用完成处理程序。
尝试在完成处理程序结束时发送释放或自动释放。那应该释放加载器提供的 reloadData 也不是异步的。
【讨论】:
以上是关于目标 C:块案例中的内存管理的主要内容,如果未能解决你的问题,请参考以下文章