首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >didReceiveMemoryWarning、viewDidUnload和dealloc

didReceiveMemoryWarning、viewDidUnload和dealloc
EN

Stack Overflow用户
提问于 2011-02-21 18:52:06
回答 4查看 12.3K关注 0票数 19

我查阅了大量的帖子,我的书籍和苹果开发者,并收集了我对使用这些信息所需要的大部分理解。如果有人能确认我做对了(或纠正我),并回答这两个问题,我将非常感激。

非常感谢,

克里斯。

邮件顺序--一般情况下,消息将按以下顺序显示:

  • didReceiveMemoryWarning
  • viewDidUnload (可由1引起)-显然只适用于视图控制器Classes.
  • dealloc

didReceiveMemoryWarning

当系统内存不足时调用。

默认情况下,视图控制器是为内存警告通知注册的,在模板方法中,如果超级didReceiveMemoryWarning没有超级视图,对它的调用会释放视图,这是一种检查视图是否可见的方法。它通过将其属性设置为零来释放视图。

动作-释放任何你不需要的东西,很可能会取消你在viewDidLoad中设置的东西。不要发布UI元素,因为这些元素应该由viewDidUnload发布。

Question1 --它似乎会被调用,即使视图是可见的,所以很难看到您可以安全发布什么。理解这一点和一些可以发布的示例将是非常有帮助的。

viewDidUnload

每当非可见视图控制器的View属性设置为零时(手动调用或最常见的是通过didReceiveMemoryWarning调用)。

有了viewDidUnload方法,您就可以:-清理您想要的任何其他东西,以节省额外的内存,或者--如果您保留了一些IBOutlets,则可以帮助释放那些在卸载视图时不会释放的内存。

操作-通常,在dealloc中发布的任何IBOutlets都应该在此方法中释放(并将引用设置为零)。请注意,如果将属性设置为release,则将其设置为nil也将释放它们。

dealloc

当视图控制器对象被取消分配时调用,当保留计数降到零时调用。

动作-释放类保留的所有对象,包括但不限于保留或复制的所有属性。

弹出视图控制器和内存

问题2-弹出视图是否将其从内存中删除?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-02-21 20:36:06

一些更正和建议:

  • didReceiveMemoryWarning practices

如前所述,如果“安全地”执行didReceiveMemoryWarning,控制器的默认实现会释放它的视图。虽然从苹果的文档中还不清楚“安全”意味着什么,但人们普遍认为它没有superview (因此目前无法看到该视图),而且它的loadView方法可以毫无问题地重建整个视图。

重写didReceiveMemoryWarning时的最佳实践是根本不尝试释放任何视图对象。如果不再需要,只需释放您的自定义数据。关于视图,只需让超类的实现来处理它们。

然而,有时数据的必要性可能取决于您的视图状态。在大多数情况下,这些自定义数据是在viewDidLoad方法中设置的。在这些情况下,“安全发布自定义数据”意味着您知道在视图控制器再次使用自定义数据之前将调用loadViewviewDidLoad

因此,在您的didReceiveMemoryWarning中,首先调用超类实现,如果它的视图被卸载,那么释放自定义数据,因为您知道loadViewviewDidLoad肯定会再次被调用。例如,

代码语言:javascript
复制
- (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而不是。

  • Others...

从技术上讲,保留数可能不会降到零。对象更有可能只是在没有事先将计数设置为零的情况下被解除分配。

为了确保,由于内存警告,默认情况下视图控制器本身通常不会被释放。

票数 31
EN

Stack Overflow用户

发布于 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-弹出视图是否将其从内存中删除?

不一定。这是一个您不应该关心的实现细节。不管目前的做法是什么,苹果可能会在下一个版本中改变它。

票数 8
EN

Stack Overflow用户

发布于 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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5069978

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档