在非常好的书“开始iPhone开发”(Apress)中,在第9章中,他们解释了如何使用导航控制器和分层表视图构建应用程序。
如果使用“仪器/活动”监视器启动应用程序,则应用程序运行良好但存在一个大问题:每次从表视图向下钻取到子表时,需要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];
}
现在,如果你运行应用程序,内存就会很好地释放!但是,如果您尝试在已经“访问过”的子表中向下钻取,则应用程序会崩溃。
我们如何正确释放内存?
提前谢谢。
答案 0 :(得分: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
亲切的问候
答案 1 :(得分:1)
我不知道工具“Clang Checker”。谢谢,你花时间去测试它。 “Clang Checker”看起来非常强大,我会试一试。
我完全同意你的RootViewController:“nextController”不是泄漏,而是一个内存 - 食客。如果您使用乐器/活动监视器运行应用程序,则应用程序在开始时需要7 Mo,每次进入子表时,它需要1 Mo的内存:
所以最后应用程序崩溃(如果我记得很清楚,一个应用程序不能超过40Mo)并且该应用程序在内存管理方面不遵循Apple规则。
通过我的修改,当你进入子表时,它需要一个1Mo的内存,但是当你回到“root”表时,会释放1Mo的内存。你可以进入另一个子表,回来,释放内存。 “唯一”的问题是如果你再次访问已经访问过的子表,应用程序崩溃了。所以,我正在寻找一种解决方案来强制应用程序在访问子表后释放内存。
为了检查,使用乐器/活动监视器,我已经按照Apple设置应用程序使用的内存(分层表视图应用程序)。当你进入子表时,需要1 Mo的记忆,但是当你回来时,记忆就被释放了。
答案 2 :(得分:0)
控制器未被释放,因为self.controllers会保留它(NSArray等集合会保留放入其中的对象)。在第二个代码块中,您正在创建一个完全独立的对象,立即泄漏它,然后过度释放您从self.controllers中取出的控制器(这会导致您的崩溃)。
看起来这段代码打算在程序的生命周期内保留它的控制器,所以这本身并没有错。你在记忆中成长的事实表明你正在创造新的物体。我会寻找对+ alloc,+ copy或-retain的调用,这些调用没有相应的调用+ autorelease或+ release。在Instruments中,使用ObjectAllocation和Leaks工具来识别过度保留的特定内存以及创建的点。创建点并不能准确地告诉您错误的位置,但通常这是一个很好的提示。
要了解您在此处实施的深入分析模式,您应该研究SimpleDrillDown示例代码。
当然,所有可可学生都应该Memory Management Rules致心。它们并不复杂,但绝对有必要理解它们。如果它有帮助,我写了summary of them。