什么时候应该在 – (void)viewDidUnload而不是在-dealloc中释放对象?
什么是-(void)viewDidUnload
是有益的?
难道我不能只放在-dealloc的一切? 如果视图没有卸载,那么不会-dealloc
?
除了已经指出的内容之外,我想详细阐述-viewDidUnload
背后的逻辑。
实现它的一个最重要的原因是UIViewController
子类通常还包含对视图层次结构中各种子视图的拥有引用。 这些属性可能已经通过IBOutlets
设置,例如从一个笔尖加载,或以编程方式在-loadView
。
UIViewController
视图的附加所有权意味着,即使从视图层次结构中删除视图并释放以节省内存,视图也会释放子视图,但实际上它们不会被释放,因为UIViewController
本身仍包含其内容对这些对象拥有优秀的保留参考。 释放UIViewController
额外的这些对象的所有权,可以确保它们将被释放以释放内存。
在UIViewController
视图re-loaded
,通常会重新创build您在此处释放的对象,无论是从Nib还是通过实现-loadView
来re-loaded
。
另外请注意,在调用这个方法的时候, UIViewController
view
属性是nil
。
正如文档所述 :
在视图控制器需要释放其视图以及与该视图关联的任何对象以释放内存时,会在内存不足的情况下调用它。
在相同的情况下, dealloc
不被调用。 此方法仅在OS3及更高版本中可用。 在iPhone OS 2.x中处理相同的情况是一个真正的痛苦!
2015年7月更新 :应该注意的是, viewDidUnload
在iOS 6中被弃用,因为“视图不再在低内存条件下被清除,所以这个方法永远不会被调用。 所以,现代的build议是不要担心它,并使用dealloc
。
这是因为您通常将@property
设置为"(nonatomic, retain)"
,因此为您创build的setter将释放当前对象,然后保留参数ie
self.property = nil;
…做了一些事情:
[property release]; property = [nil retain];
因此,你是一石二鸟:内存pipe理(释放现有的对象)和分配指针为零(因为发送任何消息到零指针将返回零)。
希望有所帮助。
请记住, viewDidUnload
是视图控制器中的一个方法,不在视图中。 视图的 dealloc
方法将在视图卸载时被调用,但视图控制器的 dealloc
方法可能不会被调用,直到以后。
如果你得到的内存不足警告,并且你的视图没有显示出来,例如在你使用UIImagePickerController来让用户拍照的时候,你的视图将会被卸载并且需要在这之后重新加载。
结论:
视图控制器有一个视图属性。 通常,一个笔尖或一段代码将其他视图添加到此视图。 这通常发生在一个-viewDidLoad方法中,像这样:
- (void)viewDidLoad { [super viewDidLoad]; [self createManyViewsAndAddThemToSelfDotView]; }
另外,一个nib文件可能会创build一个button并将其附加到视图控制器的视图中。
在iPhone OS 2.2上,当从系统调用-dReReiveMemoryWarning时,必须释放一些内容才能释放内存。 如果这是有道理的,你可以释放整个视图控制器的视图。 或者只是大量的内存消耗的内容。
- (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用于释放由视图控制器本身和视图拥有的所有对象。 原因是:如果一个视图控制器持有引用视图的孩子,即一个button,引用的子视图将不会被释放,因为他们的保留计数是> = 1.它们被释放后在-viewDidUnload,他们可以得到释放从记忆里。
苹果弃用的viewWillUnload,现在你应该使用didReceiveMemoryWarning或dealloc释放你的objetcs。
在iOS 6中,UIViewController的viewWillUnload和viewDidUnload方法现在已被弃用。 如果您正在使用这些方法来释放数据,请使用didReceiveMemoryWarning方法。 如果不使用视图控制器视图,也可以使用此方法释放对视图控制器视图的引用。 在执行此操作之前,您需要testing视图不在窗口中。
如果视图控制器从导航控制器堆栈中popup,并且不保留在其他任何地方,它将被解除分配,并且将调用dealloc而不是viewDidUnload。 你应该在dealloc中释放在loadView中创build的视图,但是不需要将variables设置为nil,因为在调用dealloc之后不久,variables将不再存在。
你可以释放你所持有的任何子视图,例如你保留在你的loadView方法中的UIImageView,或者更好的是那个UIImageView中的图像。