iOS6的viewDidUnload已被弃用

64

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

例如,如果你有像添加观察者这样的东西。

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

现在我没有一种方法来移除Observer,然而每次显示视图时都会调用viewDidLoad,这导致在一段时间后有多个观察者运行并且选择器被调用多次。

我可以通过将某些清理工作移到viewDidDisappear方法中来解决这个问题,但现在我对自己所做的是否正确有些怀疑。

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

4个回答

110

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

iOS 6中,UIViewController的viewWillUnloadviewDidUnload方法已被弃用。如果你曾经使用这些方法来释放数据,请改用didReceiveMemoryWarning方法。如果视图控制器的视图未被使用,也可以使用此方法来释放对其的引用。在执行此操作之前,您需要测试该视图是否不在窗口中。

因此,在didReceiveMemoryWarning中首先要检查视图是否在窗口中,然后再删除观察者。


这可能是正确的答案。但他们删除了这条消息还是很奇怪的。我是通过跟随Paul Hegarty的幻灯片来学习SDK的,当然它们仍然适用于iOS5。我将在今年检查他的更新幻灯片,也许他会对此给出一个好的提示。 - Hons
2
@Hons 这一点并不奇怪 - 根据文档的明确规定,viewDidUnload 只有在由于内存警告而卸载视图时才会被调用。如果你在 viewDidLoad 中添加了一个观察者,并且只在 viewDidUnload 中删除它,那么很多时候你将在没有删除它的情况下被释放。这将在通知中心中留下一个悬空指针,几乎肯定会导致以后崩溃。 - Tommy
你如何检查你的视图是否在窗口内? - zakdances
4
你可以检查 view.window 是否为 nil - Groxx
12
@Groxx 注意 - 访问“View”会导致视图加载,如果它还没有加载。即使是苹果的示例代码也犯了这个错误。你应该使用 if ([self isViewLoaded] && self.view.window) - Mike Weller
1
哈哈,说得好。谢谢@MikeWeller,你是对的!我想我发现了这个问题并添加了相同的检查,但我从未回来更新这里的事情。 - Groxx

16
首先,即使 viewDidUnload 没有被弃用,您也必须在 viewDidUnloaddealloc 中注销该通知。即使在 iOS 6 之前,viewDidUnload 在大多数情况下都不会被调用,只有在低内存情况下才会被调用。因此,如果您只将其放在 viewDidUnload 而没有放在 dealloc 中,它就不会被注销,在被释放并接收到通知时可能会崩溃。因此,您必须在之前将其放入 dealloc 中,以使其正常工作。
其次,如果您以前已经正确执行了它,则不需要额外做任何事情才能在 iOS 6 中正确运行。iOS 6 中唯一的区别是根本不再卸载视图(即使在低内存情况下也是如此)。因此,与在 iOS 5 中没有遇到低内存情况时相同。由于视图没有被卸载,viewDidLoad 只会被调用一次,因此您的通知只会被注册一次。它将在 dealloc 中被注销,因为您必须将其放置在其中以使其正常工作。

10

Alex的回答很好。但我喜欢适当地配对。因此,除非视图在未被查看时需要通知,否则我通常会在viewWillAppear和viewDidDisappear中添加通知。


viewDidUnload方法在视图卸载时调用,而viewDidDisappear方法则在视图消失后调用。在iOS 6.0之前,需要在viewDidUnload方法下注销的通知现在必须在didReceiveMemoryWarning或dealloc方法中注销。 - Daniel García Baena

5

为什么不在DEALLOC函数中删除观察者? 如果您正在使用ARC,请勿调用[super dealloc]

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


整个viewDidUnload方法的目的在于,当视图控制器仍然存在时,您可以卸载视图并释放一些内容以节省内存。 - user102008
在iOS 6中,UIViewController的viewWillUnload和viewDidUnload方法现已被弃用... - Dan H
因此,您不应使用dealloc方法。因为对象尚未准备好被销毁。 - bmeulmeester
他在初始帖子中谈论删除观察者,如果他在viewDidLoad中添加观察者,那么最好的删除位置肯定是在dealloc函数中。如果他使用ARC,我已经提供了如何实现此操作的示例。 - Dan H
4
如果你在 viewDidLoad 中添加一个观察者(该方法可能会被调用多次),并在 dealloc 方法中将其移除,那么你可能会重复注册一条通知。你应该使用 viewDidAppearviewDidDisappear 方法来开始/停止监听。 - deanWombourne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接