2

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

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

我们如何才能正确释放内存?
先感谢您。

4

3 回答 3

1

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

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

  • 10次​​后,应用需要17Mo,
  • 20 次后,申请需要 27 Mo

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

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

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

于 2009-04-16T08:14:50.640 回答
1

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

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

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

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

亲切的问候

于 2009-04-15T22:21:15.857 回答
0

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

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

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

当然,所有 Cocoa 学生都应该牢记内存管理规则。它们并不复杂,但绝对有必要理解。如果有帮助,我已经对它们进行了总结。

于 2009-05-18T13:52:31.907 回答