【问题标题】:viewDidUnload sent to deallocated instance after memory warning内存警告后将 viewDidUnload 发送到已释放的实例
【发布时间】:2012-07-05 22:10:44
【问题描述】:

我遇到了一个非常有趣的情况,不知道如何解决。我将首先概述我的程序的体系结构。我有一个 UITableViewController 派生类,它也实现了我的委托协议。此表格视图中的单元格是自定义单元格,每个单元格都有一个强(分配)类型属性给委托(表格视图控制器)。委托处理一些 UI 操作。

为了重现崩溃,我加载了表格视图,然后离开它。通常在这里,表格视图将被释放,但在我的情况下,单元格仍然持有对它的强引用,因此它保留在内存中。问题是,当内存警告在此之后到达设备时,我会崩溃。我推断会发生以下情况:

  • 表格视图控制器收到内存警告
  • 它会释放所有(可重复使用的)单元
  • 在单元格的释放中,委托属性为零,因此它们向表视图控制器发送释放。
  • 当最后一个单元格的属性为 nil 时,表格视图的引用计数达到零,因此它将自行释放
  • 释放单元格后,表格视图的 didReceiveMemoryWarning 的默认实现会继续,但已经在一个已释放的僵尸对象上
  • 有时它会在僵尸上调用 viewDidUnload 并导致应用程序崩溃。

我该如何解决这种情况?

PS:显然我不使用 ARC

【问题讨论】:

    标签: ios uitableview memory-management


    【解决方案1】:

    当你设置一个委托时,你应该分配它,而不是保留它(因此单元的释放不应该向表格视图控制器发送释放消息)。

    委托对象不(也不应该)保留它们的委托。 但是,委托对象(通常是应用程序)的客户是 负责确保他们的代表在附近接受 委托消息。为此,他们可能必须保留代表 在内存管理的代码中。此预防措施同样适用于数据 消息的来源、通知观察者和行动消息的目标。笔记 在垃圾收集环境中,对 委托很强大,因为保留周期问题不适用。

    来自Concepts in Objective-C Programming

    【讨论】:

    • 小心使用这些词...您应该而不是必须。如果您知道自己在做什么,则可以保留代表...
    • 谢谢大家,确实这是正确的方法。但是你能告诉我如何从表格视图控制器(tvc)访问单元格实例吗?这对于能够将 tvc 的 dealloc 中的单元格的委托归零是必要的。
    • cellForRowAtIndexPath:。或者您可以在单元格的 dealloc 方法中将委托设置为 nil。
    • 我的意思是在删除表格视图控制器之前我想将单元格的委托属性归零,否则它们将指向已删除的对象。在 cellForRowAtIndexPath: 我实际上 创建 单元格并 需要 设置它们的委托。在单元的释放中,它也没有意义,因为在释放单元后它显然不会调用它的委托。
    • 在 dealloc 方法中将委托设置为 nil 将起作用。当你释放一个表时,它会首先向所有单元格发送一个释放消息。我说的函数是- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath,而不是- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    猜你喜欢
    • 1970-01-01
    • 2014-09-12
    • 2011-06-16
    • 1970-01-01
    相关资源
    最近更新 更多