iOS 6 – viewDidUnload迁移到didReceiveMemoryWarning?

所以从iOS 6开始, viewDidUnload已经被弃用了,现在我需要做什么?

删除它,然后将其中的所有内容迁移到didReceiveMemoryWarning ,或保留它,并且不要在didReceiveMemoryWarning做任何事情?

简而言之,在很多情况下,你不需要改变任何东西。 而且,你绝对希望简单地将viewDidUnload所有内容迁移到didReceiveMemoryWarning

一般来说,我们大多数人将IBOutlet引用设置为在viewDidUnload nil (主要是因为Interface Builder会把它放在那里)并且执行内存的一般释放(例如清除caching,轻松重新创build模型数据等)在didReceiveMemoryWarning 。 如果这样做,那么你可能不需要任何代码更改。

根据iOS 6的viewDidUnload文档:

在低内存条件下视图不再被清除,所以这个方法从来没有被调用过。

因此,您希望将IBOutlet引用的设置移至nil ,因为视图不再被清除。 在didReceiveMemoryWarning或者类似的东西中设置它们是没有意义的。

但是,如果您通过在viewDidUnload释放易重新创build的模型对象,清空caching等来响应低内存事件,那么这些内容肯定会移至didReceiveMemoryWarning 。 但是,再一次,我们大多数人已经在那里了。

最后,如果你释放了didReceiveMemoryWarning任何东西,只要确保你的代码不会依赖于它们在你popup的时候再次在viewDidLoad被重新创build,因为不会被调用(因为视图本身没有被卸载)。

正如applefreak所说,这取决于你在viewDidUnload中所做的事情。 如果你用你在viewDidUnload有什么明确的例子来更新你的问题,我们可以提供更less的抽象计划。

简短的回答:

切勿使用-didReceiveMemoryWarning进行均衡拆卸,因为它可能被永远或多次调用。 如果你在-viewDidLoad中有你的设置,把你的清理代码放在-dealloc中。


漫长的回答:

给出一个普遍的答案并不容易,因为这取决于情况。 但是,有两个重要事实要陈述:

1. -viewDidUnload已被弃用,实际上从未从iOS6及更高版本开始调用。 所以,如果你有你的清理代码,你的应用程序在这些操作系统版本下泄漏

2. -didReceiveMemoryWarning可能会被调用多次或永远不会。 所以这是一个非常糟糕的地方,以平衡拆解你创build的其他地方的对象

我的答案是看你使用属性的常见情况,例如:

 @property (strong) UIView *myCustomView // <-- this is what I'm talking about @property (assign) id *myDelegate 

在这里你必须做一些清理工作,因为你创build并拥有了自定义视图或者InterfaceBuilder创build它,但是你保留了它。 在iOS 6之前,你可能会这样做:

 - (void)viewDidLoad { self.myCustomView = [[UIView alloc] initWithFrame:…]; } - (void)viewDidUnload { // <-- deprecated! [myCustomView removeFromSuperView]; self.myCustomView = nil; } 

…因为(再次) myCustomView是一个保留的属性,由您创build和拥有,所以您必须小心并在最后“释放”它(将其设置为零)。

在iOS 6中,replace-viewDidUnload并将保留属性设置为nil的最佳位置可能是-dealloc 。 也有viewWillAppearviewDidDisappear ,但是这些不是绑定到你的视图/控制器的生命周期,而是显示周期(另一方面,-…出现的方法是完美的取消/注册通知监听!)。 因此,在每个显示之前和之后创build和销毁视图可能不合适。 dealloc是我们可以确信在控制器生命周期的最后阶段被调用的唯一方法。 请注意,如果您使用ARC,则不得调用[super dealloc]

 - (void)dealloc { self.myCustomView = nil; } 

但是,如果您使用viewDidLoad做一些视图相关的设置,可以在低内存条件下释放,其他post显示如何处理低内存情况是完全有效的。 在这种情况下,您也可以使用dealloc,但是您必须检查您的视图是否仍然存在。

ViewController的生命周期

也许这对于查看ViewController的一般生命周期也是有帮助的:

这是viewController的生命周期(以斜体表示的意思是这些方法可能被多次调用)

  • init:ViewController加载,没有可用的接口元素(IBOutlet)(全部为零)
  • viewDidLoad:已经加载了nib / storyboard,并且所有对象都可用。 用户什么也看不到
  • viewWillAppear:视图即将显示
  • viewDidAppear:视图在屏幕上
  • viewWillDisappear:视图即将消失
  • viewDidDisappear:视图刚从窗口中移除
  • viewDidUnload:从不在iOS6 / 7中调用
  • didReceiveMemoryWarning:你不知道是否,何时和多久这个被称为。 在iOS6之前,它可能会卸载视图,在iOS6之后它只是清除屏幕外的caching或者什么也不做
  • dealloc:viewController即将被销毁

所以,总结起来有很多种可能性。 什么地方现在真的取决于什么被初始化在哪里:

  • 如果在-init中创build了-dealloc:或-viewDidLoad:
  • -viewWill / DidDisappear(与-viewWill / DidAppear配对)
  • -didReceiveMemoryWarning(可能或可能不会被调用)

如果你需要知道你的UIViewController是否被解雇,你可以添加这个代码到你的viewWillDisappear:

 - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; if ([self isBeingDismissed] || [self isMovingFromParentViewController]) { // Do your viewDidUnload stuff } } 

它不是与viewDidUnload在视图控制器生命周期中一次同时调用,但在大多数情况下可以满足您的需要!

取决于你在viewDidUnload做了什么,但你可以使用didReceiveMemoryWarningdealloc来释放数据。 看到这个

在大多数典型的情况下,这个方法可以用来代替旧的viewDidUnload。

 // The completion handler, if provided, will be invoked after the dismissed controller's viewDidDisappear: callback is invoked. - (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion NS_AVAILABLE_IOS(5_0); 

Swift 2017语法:

 override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) { if (yourChildViewController != nil) { print("good thing we did this!") } yourChildViewControllerProperty = nil super.dismiss(animated: flag, completion: completion) }