1

概述

  • 在一个 iOS 项目中,我有一个UITableView并且我正在尝试移动一行 UITableView。
  • 在我的模型中,数据的顺序已经改变,所以我试图在表格中直观地显示它,这就是我使用UITableView's 方法的原因moveRowAtIndexPath:toIndexPath:
  • 为此,我创建了一个NSIndexPath实例,并将其传递给 UITableView 的方法。

当泄漏发生时

  • 当您使用 NSIndexPath 方法创建一个实例时indexPathForRow: section:(如代码部分所示),然后将其传递给UITableView's 方法moveRowAtIndexPath: toIndexPath:,它会泄漏。

笔记:

  • 我正在使用 ARC(自动引用计数)
  • XCode 4.3.1
  • 我使用 Instruments (Xcode menu - Product > Profile) 来确定内存泄漏

代码:(在 UITableViewController 内)

NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:newRow inSection:0]; //leaking

[self.tableView beginUpdates];
[self.tableView moveRowAtIndexPath:originalIndexPath toIndexPath:newIndexPath]; //I think this causes the leak
[self.tableView endUpdates];

我尝试过的步骤

  • 注释掉对方法的调用moveRowAtIndexPath:originalIndexPath toIndexPath:,防止内存泄漏
  • 我手动使用过CFRelease(不确定这是自动引用计数环境中的好习惯)

    CFRelease((__bridge void *)toIndexPath);

问题:

  • 为什么会出现这种情况?有什么解决办法吗?
  • 仪器的内存泄漏结果是否准确?
  • UITableView 的方法有错误moveRowAtIndexPath:originalIndexPath toIndexPath:吗?
  • CFRelease 是一种选择吗?如果 CFRelease 尝试释放已释放的内存,是否有一种安全的方法可以防止应用程序崩溃(请参阅上面的确切代码)。
4

2 回答 2

1

您发布的代码不应导致 ARC 设置中的内存泄漏(也不应该没有 ARC)。

如果您确实怀疑存在错误(例如 UITableView 无法释放 NSIndexPath 对象),您可能会尝试手动释放它作为临时解决方法。但是,您确定它只是在动画完成后不释放它吗?即使您没有动画,也可能是 indexPath 对象直到遇到空闲循环才被释放(这在 GUI 组件中很常见,显然也适用于自动释放的对象)。

但是,为了确认确实是泄漏,请尝试调查从长远来看内存是否随时间增加(可能是 UITableView 坚持其最新的 indexPath 对象,这可能不是问题) . 此外,尝试使用 NSZombieEnabled 环境变量集运行调试器。当您尝试双重释放对象时,这将检测并闯入调试器。

于 2012-03-20T11:43:32.633 回答
1

我没有足够的代表来添加评论,所以我必须添加一个答案。我也看到了这个泄漏。我没有使用 ARC,也没有使用 beginUpdates/endUpdates 来包装对 moveRowAtIndexPath:toIndexPath: 的单个调用:每当我调用此方法时,Instruments 都会声明 NSIndexPath 的 32 字节泄漏。

对 NSIndexPath 的 indexPathForRow:inSection: 的调用应该返回一个不需要手动释放的自动释放对象。我怀疑 moveRowAtIndexPath:toIndexPath: 错误地保留了对象,导致泄漏。

我在调用 moveRowAtIndexPath:toIndexPath: 之前和之后添加了一些调试代码来记录 NSIndexPath 的 retainCount 并在之前得到 1(它在自动释放池中,所以这是预期的)和之后得到 5(除非已添加,否则绝对不会预期)再到自动释放池 4 次!)

编辑:另请参阅https://devforums.apple.com/message/639904(需要 Apple 开发者帐户)

于 2012-04-09T08:07:49.533 回答