我什么时候应该在 - (void)viewDidUnload而不是-dealloc中释放对象?

时间:2009-07-21 12:08:51

标签: iphone objective-c ios cocoa-touch memory-management

-(void)viewDidUnload有什么用?

我可以不仅仅重温-dealloc中的所有内容吗?如果视图卸载了,那么无论如何都不会调用-dealloc吗?

8 个答案:

答案 0 :(得分:51)

除了已经指出的内容之外,我还想详细说明-viewDidUnload背后的逻辑。

实现它的最重要原因之一是UIViewController子类通常还包含对视图层次结构中各种子视图的拥有引用。例如,当从笔尖加载时,或者以编程方式在IBOutlets内加载时,可以通过-loadView设置这些属性。

UIViewController对子视图的额外所有权意味着即使从视图层次结构中删除其视图并释放以保存内存(视图也通过其释放子视图),它们实际上也不会被释放因为UIViewController本身仍然包含对这些对象的突出保留引用。释放这些对象的UIViewController额外所有权可确保它们被释放以释放内存。

您在此处发布的对象通常会在UIViewController视图为re-loaded时重新创建并再次设置,无论是来自Nib还是通过-loadView的实现。

另请注意,调用此方法时UIViewController view属性为nil

答案 1 :(得分:21)

作为documentation says

  

在低内存条件下调用它时,视图控制器需要释放其视图以及与该视图关联的任何对象以释放内存。

在同样的情况下dealloc 被调用。此方法仅适用于OS3及更高版本。处理iPhone OS 2.x中的相同情况真的很痛苦!

2015年7月更新:应该注意的是,iOS 6中不推荐使用viewDidUnload,因为“在低内存条件下不再清除视图,因此永远不会调用此方法。”所以,现代建议不要担心它并使用dealloc

答案 2 :(得分:9)

这是因为您通常会将@property设置为"(nonatomic, retain)",因此为您创建的setter会释放当前对象,然后保留参数,即

self.property = nil;

......做了类似的事情:

[property release];
property = [nil retain];

因此,您只用一石二鸟:内存管理(释放现有对象)并将指针指定为nil(因为将任何消息发送到nil指针将返回nil)。

希望有所帮助。

答案 3 :(得分:8)

请记住,viewDidUnload是视图控制器中的方法,而不是视图中的方法。视图卸载时将调用视图的 dealloc方法,但视图控制器的 dealloc方法可能要到稍后才会被调用。

如果您收到内存不足警告并且未显示您的视图,例如,您将使用UIImagePickerController让用户拍照时,您的视图将被卸载并需要在以后重新加载这一点。

答案 4 :(得分:6)

<强>结论:

视图控制器具有视图属性。通常,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.在-vi​​ewDidUnload中释放它们后,它们可以被释放从记忆中恢复过来。

答案 5 :(得分:6)

Apple弃用了viewWillUnload,现在你应该使用didReceiveMemoryWarning或dealloc来发布你的对象。

  

在iOS 6中,viewWillUnload和viewDidUnload方法   UIViewController现已弃用。如果您使用这些方法   要发布数据,请改用didReceiveMemoryWarning方法。您   也可以使用此方法释放对视图的引用   控制器的视图是否未被使用。你需要测试一下   在执行此操作之前,视图不在窗口中。

答案 6 :(得分:5)

如果视图控制器从导航控制器堆栈中弹出并且未在其他任何位置保留,则将取消分配,并且将调用dealloc而不是viewDidUnload。您应该在dealloc中释放在loadView中创建的视图,但没有必要将变量设置为nil,因为在调用dealloc后不久,变量将不再存在。

答案 7 :(得分:3)

您可以释放您保留的任何子视图,例如您在loadView方法中保留的UIImageView,或者更好的是UIImageView上的图像。