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
。 也有viewWillAppear
和viewDidDisappear
,但是这些不是绑定到你的视图/控制器的生命周期,而是显示周期(另一方面,-…出现的方法是完美的取消/注册通知监听!)。 因此,在每个显示之前和之后创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
做了什么,但你可以使用didReceiveMemoryWarning
或dealloc
来释放数据。 看到这个
在大多数典型的情况下,这个方法可以用来代替旧的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) }