iOS6中不再调用viewDidUnload方法。

21

我刚刚安装了最新版本的Xcode/ios6。viewDidUnload现在已经过时了。

在苹果文档中,

viewDidUnload [...] 在iOS 6.0中已弃用。视图不再在低内存情况下被清除,因此不会调用此方法。

但许多应用程序仍使用此回调来释放其属性,例如:

- (void)viewDidUnload {
    [super viewDidUnload];

    self.recipientButton = nil;
    self.connectButton = nil;
    self.infoLabel = nil;
}

这是释放IBOutlets的最佳实践。

那么,第一个问题:
iOS 6中的现有应用程序会发生什么?它们会泄漏吗?

第二个问题:
释放IBOutlet属性的新推荐方法是什么?在dealloc方法中吗?

3个回答

22

对于第一个问题:

您的ViewController将会收到didReceiveMemoryWarning方法的回调,您可以在此方法中将视图和其他组件设置为nil。

如果您还没有查看过WWDC 2012视频关于“VIEW CONTROLLER的演进”的演示,请参考一下(我相信这些视频仅适用于注册开发人员,但不确定)。

回答您的第二个问题。

在dealloc方法中使用[object release];,不需要在释放之前将对象赋值为nil。


当然,在dealloc中使用[object release];只有在你运行ARC时才可能。 - user577537
7
WWDC 2012 视频的View Controllers部分文字翻译: “viewWillUnload 和 viewDidUnload。我们不再调用它们了。我的意思是,我们经过成本效益分析后决定这样做。在早期阶段,确保在内存警告时卸载视图对我们来说有真正的性能需求。会卸载各种图形和后备存储等。现在我们会独立于视图卸载它们,因此对于这些被卸载不那么重要,而且以前存在太多指针错误。” - Rose Perrone
3
我们发现未被清除的未加载视图,并最终认为自动调用它们不值得,因此我们将废弃这些方法。您仍然可以获得相同的行为。您的视图控制器仍将收到“didReceiveMemoryWarning”,如果他们愿意,他们可以将该视图设置为nil。它将按预期工作。您可能需要先检查视图是否在窗口中,然后再将其设置为nil。我提到这一点是因为有些应用程序实际上使用viewWillUnload、viewDidUnload作为摆脱其他资源的手段,而这些资源并不一定相关。 - Rose Perrone
3
视图本身并不需要特别关注,因此现在的代码可能需要转移到didReceiveMemoryWarning中。 - Rose Perrone
我发现在某些情况下,使用iOS 6时,后备存储(例如视图控制器的视图)没有被卸载。一个简单的例子是重复将一个新的视图控制器实例推入导航控制器中。在iOS 6中,我看到物理内存空闲运行降至约8MB,低内存警报被触发,并且应用程序在最终被操作系统杀死之前无法恢复任何其他内存。一个解决方案是在didReceiveMemoryWarning上检查当前视图控制器的视图是否已加载并且不可见,并将其卸载/设置为nil。 - Ari Braginsky
显示剩余2条评论

9

我建议您在IBOutlets中使用weak属性,例如:

@property (weak) IBOutlet UILabel * labelText;

这样你就不需要在dealloc中做任何事情了。在iOS 6中,仅ViewDidUnload不会调用,在iOS5或更早版本中只有在出现内存警告时才会调用。


1
第二个问题:释放 IBOutlet 属性的新推荐方式是什么?在 dealloc 方法中吗?
“旧”的推荐方式是什么?你必须始终在 dealloc 中释放保留的实例变量;这一直是这样,现在仍然是这样。
只是在 viewDidUnload 中(仅在低内存时调用)您也可以将属性设置为 nil。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接