我查阅了大量的帖子,我的书籍和苹果开发者,并收集了我对使用这些信息所需要的大部分理解。如果有人能确认我做对了(或纠正我),并回答这两个问题,我将非常感激。
非常感谢,
克里斯。
邮件顺序--一般情况下,消息将按以下顺序显示:
didReceiveMemoryWarning
当系统内存不足时调用。
默认情况下,视图控制器是为内存警告通知注册的,在模板方法中,如果超级didReceiveMemoryWarning没有超级视图,对它的调用会释放视图,这是一种检查视图是否可见的方法。它通过将其属性设置为零来释放视图。
动作-释放任何你不需要的东西,很可能会取消你在viewDidLoad中设置的东西。不要发布UI元素,因为这些元素应该由viewDidUnload发布。
Question1 --它似乎会被调用,即使视图是可见的,所以很难看到您可以安全发布什么。理解这一点和一些可以发布的示例将是非常有帮助的。
viewDidUnload
每当非可见视图控制器的View属性设置为零时(手动调用或最常见的是通过didReceiveMemoryWarning调用)。
有了viewDidUnload方法,您就可以:-清理您想要的任何其他东西,以节省额外的内存,或者--如果您保留了一些IBOutlets,则可以帮助释放那些在卸载视图时不会释放的内存。
操作-通常,在dealloc中发布的任何IBOutlets都应该在此方法中释放(并将引用设置为零)。请注意,如果将属性设置为release,则将其设置为nil也将释放它们。
dealloc
当视图控制器对象被取消分配时调用,当保留计数降到零时调用。
动作-释放类保留的所有对象,包括但不限于保留或复制的所有属性。
弹出视图控制器和内存
问题2-弹出视图是否将其从内存中删除?
发布于 2011-02-21 20:36:06
一些更正和建议:
didReceiveMemoryWarning practices如前所述,如果“安全地”执行didReceiveMemoryWarning,控制器的默认实现会释放它的视图。虽然从苹果的文档中还不清楚“安全”意味着什么,但人们普遍认为它没有superview (因此目前无法看到该视图),而且它的loadView方法可以毫无问题地重建整个视图。
重写didReceiveMemoryWarning时的最佳实践是根本不尝试释放任何视图对象。如果不再需要,只需释放您的自定义数据。关于视图,只需让超类的实现来处理它们。
然而,有时数据的必要性可能取决于您的视图状态。在大多数情况下,这些自定义数据是在viewDidLoad方法中设置的。在这些情况下,“安全发布自定义数据”意味着您知道在视图控制器再次使用自定义数据之前将调用loadView和viewDidLoad。
因此,在您的didReceiveMemoryWarning中,首先调用超类实现,如果它的视图被卸载,那么释放自定义数据,因为您知道loadView和viewDidLoad肯定会再次被调用。例如,
- (void)didReceiveMemoryWarning {
/* This is the view controller's method */
[super didReceiveMemoryWarning];
if (![self isViewLoaded]) {
/* release your custom data which will be rebuilt in loadView or viewDidLoad */
}
}请注意不要使用self.view == nil,因为self.view假定视图是某人所需要的,并且会立即再次加载视图。
viewDidUnload方法当视图控制器viewDidUnload由于内存警告而卸载视图时,会调用。例如,如果从superview中删除视图并将控制器的view属性设置为nil,则将调用viewDidUnload方法而不是。一个微妙的问题是,即使视图控制器的视图在控制器接收到didReceiveMemoryWarning时已经被释放并设置为零,因此实际上没有视图要为控制器卸载,如果调用超类的didReceiveMemoryWarning实现,则将调用viewDidUnload。
这就是为什么手动将视图控制器的view属性设置为零并不是一个好做法。如果您这样做了,您最好也发送一个viewDidUnload消息。我想您对viewDidUnload的理解更可取,但显然这不是当前的行为。
如果您的意思是‘从超级视图中移除’弹出‘,它确实减少了视图的保留计数,但不一定要释放它。
如果您的意思是从UINavigationController中弹出,它实际上减少了视图控制器本身的保留计数。如果视图控制器没有被另一个对象保留,那么它将与视图一起被解除分配。正如我所解释的,这次将调用viewDidUnload而不是。
从技术上讲,保留数可能不会降到零。对象更有可能只是在没有事先将计数设置为零的情况下被解除分配。
为了确保,由于内存警告,默认情况下视图控制器本身通常不会被释放。
发布于 2011-02-21 20:36:49
didReceiveMemoryWarning
..。
动作-释放任何你不需要的东西,很可能会取消你在viewDidLoad中设置的东西。
这是错误的。在viewDidLoad中重新创建的任何内容都应该在viewDidUnload中发布(并设置为nil)。正如您在下面提到的,当视图可见时,也会调用didReceiveMemoryWarning。在didReceiveMemoryWarning中,您应该发布诸如缓存或其他视图控制器之类的东西,下次需要时可以懒洋洋地重新创建它们(即手动实现它们的getter )。
viewDidUnload
..。
操作-通常,在dealloc中发布的任何IBOutlets都应该在此方法中释放(并将引用设置为零)。请注意,如果将属性设置为release,则将其设置为nil也将释放它们。
对,是这样。通常,您在viewDidLoad中创建的所有内容以及声明为retain的所有IBOutlets都应该在这里发布并设置为nil。
dealloc
..。
动作-释放类保留的所有对象,包括但不限于保留或复制的所有属性。
对,是这样。值得注意的是,这包括您在viewDidUnload中处理的所有对象,因为在dealloc流程中没有隐式调用后者(AFAIK,不完全确定)。这就是为什么必须在nil中将所有发布对象设置为viewDidUnload的原因,因为否则可能会释放两次(首先在viewDidUnload中,然后在dealloc中;如果您设置指向nil的指针,则dealloc中的发布调用将没有任何效果)。
弹出视图控制器和内存
问题2-弹出视图是否将其从内存中删除?
不一定。这是一个您不应该关心的实现细节。不管目前的做法是什么,苹果可能会在下一个版本中改变它。
发布于 2013-04-12 11:52:27
只是为了更新这个线程,使其与iOS6 6相关:
viewDidUnload和viewWillUnload在iOS6中不受欢迎。这些方法从未被调用过。
有关此方法和其他不推荐的方法,请参见:http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/DeprecationAppendix/AppendixADeprecatedAPI.html
https://stackoverflow.com/questions/5069978
复制相似问题