viewDidUnload方法的弃用和向后兼容性

3
注意:我看到有些问题在这方面被问到,但似乎没有澄清我的疑惑。
在iOS6之前,所有的插座、重量级资源,如图片和声音,在viewDidUnload中设置为nil。在iOS6之后,这不再是这种情况,因为视图不再被卸载。系统调用didReceiveMemoryWarning,这是新推荐的放置这样的资源中和解决方法。
那么如果代码需要支持iOS4以上的所有内容呢?在运行iOS 4和5的设备上,viewDidUnload仍然会被调用。而在运行iOS6的设备上,只会调用didReceiveMemoryWarning。
这是否意味着我必须在两个地方复制代码?在两个地方调用一个通用方法是一个好的方法吗?请提供您的输入或处理此问题的方法。
2个回答

4
是的,如果你支持iOS 6.0之前的版本,你应该在viewDidUnload中删除与视图及其控件相关的任何内容。这是设备上运行的iOS的一个功能。显然,如果设备运行的是6.0或更高版本,则视图不会被卸载。无论如何,在didReceiveMemoryWarning中都应该清除缓存和类似的东西。
你不应该在两个方法中复制代码,因为那是不必要的。在viewDidUnload中进行与视图相关的清理,在didReceiveMemoryWarning中进行与缓存相关的清理。最重要的是,不要将viewDidUnload中的与视图特定的清理(例如将IBOutlet引用设置为nil,Interface Builder曾经向我们的代码添加过这样的内容)复制到didReceiveMemoryWarning中。如果你这样做,并且在iOS 6中收到内存警告,你将会失去未被移除的视图的IBOutlet引用。
参见:iOS 6 - viewDidUnload migrate to didReceiveMemoryWarning?

问题仍然存在,如果在运行iOS6 SDK编写的应用程序在iOS5设备上运行,viewDidUnload会被调用吗? - paiego
1
@paiego 是的,如果(a)设备运行的是 iOS 6.0 之前的版本;并且(b)您收到低内存警告;并且(c)该视图不是当前视图(即,您已经对另一个视图控制器进行了模态/推送),则会调用 viewDidUnload。这是设备 iOS 版本的功能,而不是您编译的版本。在停止支持 iOS 5 之前,您必须正确处理 viewDidUnload - Rob
@Rob:好的,但正如jxpx777所指出的那样,didReceiveMemoryWarning自iOS2以来就被调用了。如果它没有附加到窗口,为什么不在这个方法中清除VC的子视图呢?也就是说,viewDidUnload给你的东西,didReceiveMemoryWarning不能给你吗? - paiego
很不幸,我们对此持不同意见。我现在已经与ViewDidUnload一起工作了很多次,很清楚的是,只有在低内存情况下才会调用viewDidUnload。您可以在ViewDidUnload中添加断点,除非出现低内存通知,否则永远不会命中断点。苹果在iOS4中添加了viewDidUnload,并且旨在通知用户系统已经卸载了视图,任何对子视图的强引用都应该被释放。在iOS6中,苹果决定将控制权交还给应用程序,并让其确定何时清除视图。 - paiego
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/26690/discussion-between-rob-and-paiego - Rob
显示剩余3条评论

1

didReceiveMemoryWarning在iOS 2.0及更高版本中可用, 所以为什么不将它从viewDidUnload移动到didReceiveMemoryWarning中,使得所有人都可以使用呢?


1
Interface Builder通常用于在viewDidUnload中向nilIBOutlet引用添加代码。这绝对不应该移动到didReceiveMemoryWarning,因为这会给iOS 6用户带来问题。 - Rob

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