iOS6 viewDidUnload 已弃用

Posted

技术标签:

【中文标题】iOS6 viewDidUnload 已弃用【英文标题】:iOS6 viewDidUnload Deprecated 【发布时间】:2012-09-26 13:52:57 【问题描述】:

也许这是一种不好的做法,但从我阅读的文档中,我得到了一些建议,即在某些情况下在 viewDidLoad 方法中初始化对象,并在 viewDidUnload 中将其设为 nil。

例如,如果您有添加观察者之类的东西

[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(filterready:)
                                                 name:@"filterReady"
                                               object:nil];

现在我没有删除观察者的方法,但是每次显示视图时都会调用 viewDidLoad,这会导致一段时间后有多个观察者运行,然后选择器会被多次调用。

我可以通过将一些清洁器移入 viewDidDisappear 方法来解决此问题,但现在我怀疑我是否做对了。

在我的示例中,我有多个导航控制器来控制它们的子导航,但从不为它们调用 dealloc,即使它们没有被引用

【问题讨论】:

【参考方案1】:

您应该使用 - (void)didReceiveMemoryWarning- (void)dealloc 方法。

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

所以你应该先检查你的视图是否在窗口中,然后在didReceiveMemoryWarning中移除你的观察者

【讨论】:

这可能是正确的答案。仍然很奇怪,他们删除了此消息。我按照 Paul Hegarty 的幻灯片学习了使用 SDK,当然它们仍然适用于 iOS5。我将检查他今年更新的幻灯片,也许他对此给出了很好的暗示。 @Hons 这一点都不奇怪——viewDidUnload 是,根据文档明确地,仅当您的视图因内存警告而被卸载时才会调用。如果您在viewDidLoad 中添加一个观察者并仅在viewDidUnload 中删除它,那么很多时候您将被释放而不删除它。这将在通知中心留下一个悬空的指针,几乎可以肯定会导致稍后崩溃。 @yourfriendzak 你可以检查view.window 是否为零。 @Groxx 但请注意 - 访问“视图”将导致视图被加载(如果尚未加载)。甚至 Apple 在其示例代码中也犯了这个错误。你应该使用if ([self isViewLoaded] && self.view.window) 哈,好点子。谢谢@MikeWeller,你是对的!我想我发现了这一点并添加了相同的检查,但我再也没有回来更新这里的内容。【参考方案2】:

首先,即使viewDidUnload 未被弃用,您也必须在viewDidUnloaddealloc 中取消注册该通知。即使在 iOS 6 之前,viewDidUnload 在大多数情况下也不会被调用;仅在内存不足的情况下。所以如果你之前只把它放在viewDidUnload而不是dealloc,它就不会被取消注册,它可能会在它被释放并收到通知时崩溃。所以你必须先把它放在dealloc,它才能正常工作。

其次,如果你之前做得正确,你不需要做任何额外的事情来让它在 iOS 6 中正常工作。iOS 6 中唯一的区别是视图不再被卸载(即使在低内存中)情况)。因此,当您没有遇到内存不足的情况时,它与 iOS 5 中的情况相同。由于未卸载视图,viewDidLoad 只会被调用一次,因此您的通知只会被注册一次。它将在 dealloc 中取消注册,因为您必须将其放入它才能正常工作。

【讨论】:

【参考方案3】:

Alex 的回答很好。但我喜欢适当的配对。出于这个原因,除非视图需要在它甚至没有看到时被通知,否则我通常会在 viewWillAppear 和 viewDidDisappear 添加通知

【讨论】:

viewDidUnload 在视图卸载时调用,viewDidDisappear 仅在视图消失时调用。必须在 viewDidUnload 方法下注销的通知,现在,从 iOS 6.0 开始,必须使用 didReceiveMemoryWarning 或 dealloc 注销【参考方案4】:

为什么不直接删除 DEALLOC 函数中的观察者呢? 如果你使用 ARC,不要调用 [super dealloc]

如果您查看控制器 dealloc 函数没有被调用,那么您需要找出原因。也许你在 ViewController 上运行了一个 NSTimer,当你弹出视图时,这会导致 dealloc 不会被调用。或者视图被保留在其他地方。

【讨论】:

viewDidUnload 的全部观点是,当视图控制器仍然存在时,您可以卸载视图并释放内容以节省内存 在 iOS 6 中,UIViewController 的 viewWillUnload 和 viewDidUnload 方法现已弃用...... 因此你不应该使用 dealloc 方法。因为对象还没有准备好被销毁。 他在最初的帖子中谈到了删除观察者,如果他在 viewDidLoad 中添加了观察者,那么删除它的最佳位置肯定是在 dealloc 函数中。如果他使用 ARC,我已经提供了一个示例说明如何执行此操作。 如果您在viewDidLoad 中添加一个观察者(可以多次调用)并在dealloc 中删除它,您可能会多次注册通知。您应该使用viewDidAppearviewDidDisappear 开始/停止收听。

以上是关于iOS6 viewDidUnload 已弃用的主要内容,如果未能解决你的问题,请参考以下文章

从项目的视图控制器中删除所有 -viewDidUnload 的方法

TWTweetComposeViewController 在 IOS6 中已弃用

viewdidunload 根本没有被调用

应该将 viewDidUnload 中的哪些工作移至 didReceiveMemoryWarning?

PHP 已弃用:each() 函数已弃用 [重复]

已弃用:指令 'allow_url_include' 在第 0 行的 Unknown 中已弃用