【发布时间】:2010-11-12 15:03:47
【问题描述】:
-(void)viewDidUnload 有什么用处?
我能不能只发布-dealloc 中的所有内容?如果视图确实卸载了,-dealloc 不会被调用吗?
【问题讨论】:
标签: iphone objective-c ios cocoa-touch memory-management
-(void)viewDidUnload 有什么用处?
我能不能只发布-dealloc 中的所有内容?如果视图确实卸载了,-dealloc 不会被调用吗?
【问题讨论】:
标签: iphone objective-c ios cocoa-touch memory-management
当视图控制器需要释放其视图以及与该视图关联的任何对象以释放内存时,在内存不足的情况下调用它。
在同样的情况下,dealloc不被调用。此方法仅适用于 OS3 及以上版本。在 iPhone OS 2.x 中处理同样的情况真的很痛苦!
2015 年 7 月更新:应该注意的是,viewDidUnload 在 iOS 6 中已被弃用,因为“在内存不足的情况下不再清除视图,因此永远不会调用此方法。”所以,现代的建议是不要担心它并使用dealloc。
【讨论】:
您可以释放您持有的任何子视图,例如您在 loadView 方法中保留的 UIImageView,或者更好的是该 UIImageView 上的图像。
【讨论】:
请记住,viewDidUnload 是视图控制器中的方法,而不是视图中的方法。 视图的 dealloc 方法将在视图卸载时被调用,但视图控制器的 dealloc 方法可能要稍后才能调用。
如果您收到内存不足警告并且您的视图未显示(例如,大约在您使用 UIImagePickerController 让用户拍照时发生),您的视图将被卸载并且需要在之后重新加载那个。
【讨论】:
除了已经指出的内容之外,我还想详细说明-viewDidUnload 背后的逻辑。
实现它的最重要原因之一是UIViewController 子类通常还包含对视图层次结构中各种子视图的拥有引用。例如,这些属性可以在从 nib 加载时通过IBOutlets 设置,或者以编程方式在-loadView 中设置。
UIViewController 对子视图的额外所有权意味着即使将其视图从视图层次结构中移除并释放以节省内存,通过这子视图也被视图释放,它们实际上不会被释放,因为UIViewController 本身仍然包含对这些对象的未完成保留引用。释放这些对象的 UIViewController 额外所有权可确保它们也将被释放以释放内存。
当UIViewController 视图为re-loaded 时,您在此处释放的对象通常会重新创建并重新设置,无论是来自 Nib 还是通过 -loadView 的实现。
另请注意,在调用此方法时,UIViewControllerview 属性为 nil。
【讨论】:
结论:
视图控制器有一个视图属性。通常,一个 nib 或一段代码会向该视图添加其他视图。这经常发生在 -viewDidLoad 方法中,如下所示:
- (void)viewDidLoad {
[super viewDidLoad];
[self createManyViewsAndAddThemToSelfDotView];
}
此外,nib 文件可能会创建一个按钮并将其附加到视图控制器的视图中。
在 iPhone OS 2.2 上,当从系统调用 -didReceiveMemoryWarning 时,您必须释放一些东西来释放内存。如果有意义,您可以释放整个视图控制器的视图。或者只是其中的大量消耗内存的内容。
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
现在,在新的 OS 3.0 中,有一个 -viewDidUnload 方法,当视图因内存不足而被卸载时,系统会调用该方法(请纠正我:这个方法究竟是什么时候调用的?)
-viewDidUnload 用于释放视图控制器本身和视图拥有的所有对象。原因:如果视图控制器持有对视图子视图的引用,即按钮,则被引用的子视图不会被释放,因为它们的保留计数> = 1。它们在-viewDidUnload中释放后,它们可以被释放凭记忆。
【讨论】:
这是因为您通常会将@property 设置为"(nonatomic, retain)",因此为您创建的设置器会释放当前对象,然后保留参数,即
self.property = nil;
...按照以下方式做一些事情:
[property release];
property = [nil retain];
因此,您是用一块石头杀死两只鸟:内存管理(释放现有对象)并将指针分配给 nil(因为向 nil 指针发送任何消息都将返回 nil)。
希望对您有所帮助。
【讨论】:
如果视图控制器从导航控制器堆栈中弹出并且没有保留在其他任何地方,它将被释放,并且会调用 dealloc 而不是 viewDidUnload。你应该在dealloc中释放在loadView中创建的视图,但不必将变量设置为nil,因为调用dealloc后变量将不再存在。
【讨论】:
Apple 已弃用 viewWillUnload,现在您应该使用 didReceiveMemoryWarning 或 dealloc 来释放您的对象。
在 iOS 6 中,viewWillUnload 和 viewDidUnload 方法 UIViewController 现在已弃用。如果您使用这些方法 要释放数据,请改用 didReceiveMemoryWarning 方法。你 也可以使用该方法释放对视图的引用 控制器的视图(如果它没有被使用)。你需要测试一下 执行此操作之前视图不在窗口中。
【讨论】: