![](/img/trans.png)
[英]Root View controller is deallocated so how do I retain it or add it to my navigation controller again
[英]iOS Development: Why are the retain counts for my view controller so strange?
我正在深入研究iOS开发,我正在构建一个基于导航的应用程序,该应用程序未完全释放被推送到导航堆栈的其中一个视图。 这是有问题的,因为视图控制器永远不会被释放,因此每次将视图控制器推入堆栈时,它使用的内存就会建立起来。 因此在调查问题后,我发现视图控制器的保留计数非常奇怪。 一旦倒计时器达到零,所讨论的视图控制器就被推到堆栈。
这是在计时器回调中创建视图控制器的代码,显示其保留计数,并将其推送到导航堆栈...
-(void)updateCountDownTimer //Defined in MyViewController_A class
{
[self setTimeRemaining:([self timeRemaining] - 1)];
[[self countDownLabel] setAlpha:1];
[[self countDownLabel] setText:[NSString stringWithFormat:@"%d", [self timeRemaining]]];
//Fade out the current time
[UIView beginAnimations:@"FadeAnimation" context:nil];
[UIView setAnimationDuration:1];
[[self countDownLabel] setAlpha:0];
[UIView commitAnimations];
if ([self timeRemaining] == 0)
{
MyViewController_B *myvc_b = [[MyViewController_B alloc] initWithNibName:@"MyView_B_iPhone" bundle:nil];
[[self navigationController] pushViewController:myvc_b animated:YES];
NSLog(@"updateCountDownTimer: %d", [myvc_b retainCount]);
[myvc_b release];
[[self countDownTimer] invalidate];
[[self countDownLabel] setHidden:YES];
}
}
这是在按下暂停按钮后将视图控制器弹出导航堆栈的代码...
- (void)pauseButtonPressed:(id)sender
{
//Stop the timer
[puzzleTimer invalidate];
NSLog(@"pauseButtonPressed before pop: %d", [self retainCount]);
//return to the previous view
[[self navigationController] popViewControllerAnimated:YES];
NSLog(@"pauseButtonPressed after pop: %d", [self retainCount]);
}
这是控制台输出,显示整个过程中非常奇怪的保留计数...
2010-12-02 17:50:38.062 MyApp[821:307] updateCountDownTimer: 5
2010-12-02 17:50:40.453 MyApp[821:307] pauseButtonPressed before pop: 2
2010-12-02 17:50:40.462 MyApp[821:307] pauseButtonPressed after pop: 4
我是iOS开发的新手,但代码对我来说似乎很简单,所以我不知道我缺少什么。
非常感谢您的智慧!
更新 :看起来Leaks仪器报告了将前一个视图控制器推入堆栈的代码行上的泄漏(即负责推送视图控制器的视图控制器)。 代码再次非常简单,所以我不知道它为什么报告泄漏......
MyViewController_A *myvc_a = [[MyViewController_A alloc] initWithNibName:@"MyView_A_iPhone" bundle:nil];
[[self navigationController] pushViewController:myvc_a animated:YES]; //<--Leak being reported here
[myvc_a release];
* 更新: *发现问题,就像每个人都在说和下面评论中发布的链接中显示的问题一样,我的活动对象仍然引用我的视图控制器,这阻止了它的解除分配。 在我的情况下,我有两个定时器瞄准我的视图控制器,这些定时器在我从堆栈弹出视图之前没有失效,这意味着有两个活动对象仍然引用视图控制器。 这是我在Apple文档中找到的一个片段,揭示了这个问题......
也许更重要的是,计时器也能保持对目标的强烈参考。 这意味着只要计时器保持有效(并且您正确遵守内存管理规则),其目标将不会被释放。
无论如何,再次感谢所有帮助过的人!
你没有遗漏任何东西 - UINavigationController
实例只是在内部对保留计数做了奇怪的,奇怪的事情。
如果您发现要尝试修补的特定内存泄漏,则应该只担心retainCount
。 在这种情况下,当然,你有问题... retainCount
只是没有帮助,因为它是如此奇怪。
你可以检查弹出时是否在MyViewController
调用了dealloc。 此外,在测试之前,请注释掉检查retainCount的行。 调用retainCount
有时会添加到retainCount
。
要真正确定正在发生的事情,请在Xcode中转到“运行”菜单,然后选择“使用性能工具运行”>“泄漏”。 按下并弹出该视图控制器,您应该看到它弹出为泄漏。 您将能够看到对象上的所有retain
和release
调用。
如果你真的陷入困境,Apple的Finding Leaks指南会有一些更聪明的解决方案。 祝好运!
就内存管理而言,您的代码没有任何问题。
您不应该依赖保留计数来检查您的对象是否正在被正确释放,因为系统也将保留它所需要的并在适当时释放。 例如,当您将视图控制器添加到堆栈时,它会被导航控制器及其子视图保留,当它弹出时,它会发送一条释放消息,传播其所有子视图。
一般规则是,如果您分配,保留或复制对象,则您有责任将其释放。 其他所有内容都由系统处理,并将使用自动释放池进行刷新。
从来没有,永远不会看到对象的保留计数。 它们不应该以编程方式使用,并且在您尝试调试代码时会产生误导。
原因如下:您知道在您的代码中,您正在调用保留和释放来管理您的保留计数。 但是你也可能正在调用-autorelease,这会导致你的保留计数在以后很少或根本没有控制权的情况下递减。 更糟糕的是,每当您将对象的引用传递给您不控制实现的对象(可能发生在您创建的大多数对象上)时,接收对象可以自行调整保留计数 - 并且该对象可以将您的对象传递给其他对象,这也会调整保留计数。
关键是,您不应该出于任何原因随时查看对象的保留计数。 他们只会让你感到困惑。 您的工作是正确管理您对对象的声明,并相信其他人编写的代码也是如此。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.