【问题标题】:Objective C: Memory management in Block cases目标 C:块案例中的内存管理
【发布时间】: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 有什么原因吗?

标签: objective-c memory-management objective-c-blocks


【解决方案1】:

几个问题:

  • 没有理由将loader 声明为__block;您没有在块中重新分配,因此,__block 毫无意义。

  • 泄漏是因为你alloc/init加载器,但从未释放它

  • 不要命名方法getSomethingget 前缀是为通过引用返回内容的方法保留的。就叫它objects。如果它应该触发负载,则调用它loadperformLoad

如果是异步的,那么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 也不是异步的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-25
      • 2013-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多