【问题标题】:Hierarchical TableView memory never released分层 TableView 内存从未释放
【发布时间】:2010-10-19 16:45:53
【问题描述】:

在非常好的书籍“iPhone 开发入门”(Apress)的第 9 章中,他们解释了如何使用导航控制器和分层表视图构建应用程序。
如果您使用 Instrument/Activity 监视器启动应用程序,应用程序运行良好但有一个大问题:每次从表视图向下钻取到子表时,它会多占用 1Mo 内存!并且这个内存永远不会被释放,当然,最后应用程序会崩溃。 对我来说,问题来自“RootViewController.h”的以下方法:
(原始源代码是这个ZIP file的“09 Nav”)

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger row = [indexPath row];
    SecondLevelViewController *nextController = [self.controllers objectAtIndex:row];

    NavAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    [delegate.navController pushViewController:nextController animated:YES];

}

在这个方法中,“nextcontroller”永远不会被释放。为了使用命令[nextController release];我做了以下修改:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger row = [indexPath row];
    SecondLevelViewController *nextController = [[SecondLevelViewController alloc] init ];
    nextController = [self.controllers objectAtIndex:row];
    NavAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    [delegate.navController pushViewController:nextController animated:YES];
    [nextController release];
}

现在,如果您运行该应用程序,内存就会很好地释放!但是,如果您尝试在您已经“访问过”的子表中向下钻取,应用程序就会崩溃。

我们怎样才能正确的释放内存呢?
提前谢谢你。

【问题讨论】:

    标签: ios uitableview memory-management


    【解决方案1】:

    如果您使用 Clang 检查器 (http://clang.llvm.org/StaticAnalysis.html) 检查源代码,您将看到有 3 个泄漏:

    1) PresidentDetailController.m,对象 NSIndexPath *newPath (line 75) 永远不会被释放 2)PresidentDetailController.m,对象UITextField *textField(第166行)永远不会释放 3)PresidentsViewController.m,对象PresidentDetailController *childController(第86行)永远不会释放

    您建议的不是泄漏;您对源代码的更改是应用程序崩溃的原因。使用 Clang 检查器非常简单,看看

    http://clang.llvm.org/StaticAnalysisUsage.html#BasicUsage

    亲切的问候

    【讨论】:

      【解决方案2】:

      我不知道“Clang Checker”工具。谢谢你花时间测试它。 “Clang Checker”似乎很强大,我试试看。

      我完全同意你的观点 RootViewController:"nextController" 不是泄漏,而是内存消耗者。如果您使用 Instrument/Activity 监视器运行应用程序,一开始应用程序需要 7 Mo,每次进入子表时,它会多占用 1 Mo 内存:

      • 10次后,应用耗时17Mo,
      • 20次后,申请耗时27个月

      所以最后应用程序崩溃(如果我没记错的话,一个应用程序不能超过 40Mo)并且这个应用程序在内存管理方面不遵循 Apple 规则。

      通过我的修改,当你进入一个子表时,它会占用一个 1Mo 的内存,但是当你回到“根”表时,会释放 1Mo 的内存。你可以进入另一个子表,回来,内存被释放。 “唯一”的问题是,如果您再次进入已经访问过的子表,应用程序就会崩溃。因此,我正在寻找一种解决方案来强制应用程序在访问子表后释放内存。

      为了检查仪器/活动监视器,我已经跟踪了 Apple 设置应用程序(分层表视图应用程序)使用的内存。当你进入子表时,它需要 1 Mo内存,但是当你回来的时候,内存就被释放了。

      【讨论】:

        【解决方案3】:

        控制器没有被释放,因为 self.controllers 保留了它(NSArray 等集合保留了放入其中的对象)。在第二个代码块中,您正在创建一个完全独立的对象,立即泄漏它,然后过度释放您从 self.controllers 中拉出的控制器(这会导致您的崩溃)。

        看起来这段代码打算在程序的整个生命周期中保留它的控制器,所以这本身并没有错。您在内存中增长的事实表明您正在创建新对象。我会寻找对 +alloc、+copy 或 -retain 的调用,这些调用没有对 +autorelease 或 +release 的相应调用。在 Instruments 中,使用 ObjectAllocation 和 Leaks 工具来识别被过度保留的特定内存以及创建点。创建点并不能准确地告诉您错误在哪里,但通常它是一个很好的提示。

        要了解您在此处实现的向下钻取模式,您应该研究SimpleDrillDown 示例代码。

        当然,所有 Cocoa 学生都应该牢记Memory Management Rules。它们并不复杂,但绝对有必要理解。如果有帮助,我已经写了summary of them

        【讨论】:

          猜你喜欢
          • 2012-04-02
          • 2018-11-08
          • 1970-01-01
          • 1970-01-01
          • 2013-07-26
          • 2011-12-27
          • 1970-01-01
          • 1970-01-01
          • 2012-04-10
          相关资源
          最近更新 更多