ViewWillDisappear与dealloc

时间:2010-09-24 16:00:11

标签: iphone objective-c

我在我的视图控制器的dealloc方法中放了一个NSlog。它没有得到一致的称呼。我注意到ViewWillDisappear总是被调用。将所有整洁的upcode移到这里可以吗?将内容设置为Nil并释放调用。

有人为什么dealloc没有被调用得到一些建议?我知道它在文档中说它可能不会被调用,但如果你有一个非常简单的应用程序,它总是被调用。所以我做的事情必须影响dealloc。

这是调用我的ViewController而不是总是调用我的dealloc的代码。

-(IBAction) playComputerTapped:(id)sender
{

PlayGameViewController * pgvc = [[PlayGameViewController alloc]         initWithNibName:@“PlayGameViewController”包:[NSBundle mainBundle]];  pgvc.gameMode = 1;  [self presentModalViewController:pgvc animated:YES];  [pgvc release];     }

上面的代码将我从mailmenu ViewController带到了游戏中。

下面是离开gameViewController并带我回到菜单的代码。

[self.parentViewController dismissModalViewControllerAnimated:YES];

由于 -code

2 个答案:

答案 0 :(得分:11)

您不是指viewDidUnload而不是viewWillDisappear吗?

视图控制器消失时调用

viewWillDisappear。这通常在弹出视图控制器或将其他视图控制器推送到堆栈时发生。 viewWillDisappear的目的是停止活动 - 例如停止动画,隐藏某些元素或类似内容。

viewDidUnload可能是你的意思,因为在卸载视图控制器的视图时会调用这个。对于当前可见的视图控制器,这应该永远不会发生,仅适用于导航堆栈中某些位置的控制器(UITabBarController或UINavigationController的一部分),但当前不可见。 viewDidUnload的目的是释放属于视图的任何UI元素,并且视图控制器也保留。

要理解重要的是要了解为什么要卸载此类控制器的视图的原因。原因是内存消耗。视图占用大量内存,即使它们当前不可见。视图通常很容易重建 - 只需调用构造它们的代码即可。如果您使用Interface Builder,这尤其容易。所以这些观点是获得更多记忆的最佳候选者。

当系统没有足够的内存时,它会开始调用当前不可见的didReceiveMemoryWarning视图控制器方法。如果您已经在Xcode中使用模板创建了控制器,则此方法只需调用super(UIViewControllers)的实现[super didReceiveMemoryWarning]。该默认实现将释放self.view,而viewDidUnload又应将其与所有子视图一起解除分配。

现在让我们假设您的视图控制器需要访问某些子视图以某种方式操作它。例如,您可以在那里拥有UILabel元素,并且您希望相应地更改其内容。要访问此元素,您需要创建一个成员变量(IBOutlet)并将其连接到该元素。现在您的视图控制器拥有该标签,因此其保留计数会增加。释放控制器视图时,标签也是如此,但由于视图控制器仍保留标签,因此不会取消分配。因此,您应该使用loadView方法发布标签。

我见过以编程方式创建视图的应用程序(在didReceiveMemoryWarning方法中),但是加载是以一种脏的方式完成的,以至于在一次取消分配之后无法重建视图。因此,每次系统内存不足时,它都会调用[super didReceiveMemoryWarning],后者又会取消分配视图,但在导航回该视图后,控制器应用程序崩溃了。一个快速的“错误修正”是删除视图控制器中的调用dealloc。好吧,系统没有得到内存并且发生了一些奇怪的效果,但至少应用程序没有立即崩溃。

现在是第三个 - viewWillDisappear。当对象不属于任何人并且其内存将被释放时,将调用此方法。在这里,您需要释放您保留的所有对象。对于视图控制器,它们通常是对模型类的引用。

我想描述一个可能的场景。假设您有一个显示与其他人聊天的视图控制器。让我们说这是非常花哨的聊天,表情符号和好友图标都是动画的。假设每个聊天项都显示为UITableView的单元格。

当您的好友向您发送消息时,您希望通过重新加载将新单元格附加到表格视图中。因此,您的视图控制器有一个表视图的出口。

viewDidUnload中,你应该停止表情符号和图标的动画。 在dealloc中,您应该释放表视图。 在viewWillDisappear中,您希望释放聊天记录(可能是此会话期间发送和接收的所有消息的NSArray)。

现在,如果您离开聊天室,didReceiveMemoryWarning会被调用,您就会停止播放动画。

当系统内存不足,并且您的视图控制器不可见时,将调用viewDidUnload并释放视图。调用你的loadView并释放UITableView,以便它可以真正解除分配。

当您导航回聊天时,再次调用viewDidLoad并再次构建视图,之后调用viewWill/DidAppear。您的模型(聊天会话的表示)仍然存在,因此表视图的数据源具有与以前一样的所有数据,因此表视图将显示与取消分配视图之前完全相同的内容。在您开始制作动画的所有dealloc之后。

当您与朋友聊天时,您释放了视图控制器,并且它被取消分配 - 调用{{1}},您释放包含聊天消息的数组,并清理其他所有内容。

我希望它能让事情变得更加清晰。

答案 1 :(得分:1)

那取决于。

如果您需要减少应用的内存占用量,那么在通过viewWillDisappear无法看到视图时卸载内容是一种不错的方法。但是,一旦视图再次显示,您将需要重新初始化所有内容,具体取决于其内容,这可能会产生相当大的开销 - 甚至可能没有必要。

对于一个小应用程序(就内存使用而言),使用dealloc来卸载你的东西很好。仅当对象将计数值保持为零时才会调用它,并且是在销毁对象之前将运行的最后一个方法。使用自动释放时,情况可能并非如此,当然对象可以由除parentviewcontroller之外的某个对象保留,从而防止它被销毁,从而无法调用dealloc。

您可能需要查看Memory Management Programming Guide,它会更详细地解释一些内容。