iOS 6 - viewDidUnload 迁移到 didReceiveMemoryWarning?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12674268/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS 6 - viewDidUnload migrate to didReceiveMemoryWarning?
提问by Devfly
So with viewDidUnload
deprecated as of iOS 6, what do I need to do now?
因此,viewDidUnload
自 iOS 6 起已弃用,我现在需要做什么?
Delete it, and migrate all of it's contents in didReceiveMemoryWarning
, or leave it, and don't do anything in didReceiveMemoryWarning
?
删除它,并将它的所有内容迁移到 中didReceiveMemoryWarning
,或者保留它,并且在 中不做任何事情didReceiveMemoryWarning
?
回答by Rob
The short answer is that, in many cases, you don't need to change anything. And, you most certainly do notwant to simply migrate all of the contents of viewDidUnload
to didReceiveMemoryWarning
.
简短的回答是,在许多情况下,您不需要更改任何内容。而且,你肯定做不希望简单地迁移所有的内容viewDidUnload
来didReceiveMemoryWarning
。
Generally, most of us do the setting of IBOutlet
references to nil
in viewDidUnload
(largely because Interface Builder would put that there for us) and do the general freeing of memory (e.g. clearing of caches, releasing of easily recreated model data, etc.) in didReceiveMemoryWarning
. If that's the way you do it, then you probably don't require any code changes.
通常,我们中的大多数人都会设置IBOutlet
对nil
in的引用viewDidUnload
(主要是因为 Interface Builder 会将其放在那里给我们)并在didReceiveMemoryWarning
. 如果您就是这样做的,那么您可能不需要任何代码更改。
According to the iOS 6 viewDidUnload
documentation:
根据 iOS 6viewDidUnload
文档:
Views are no longer purged under low-memory conditions and so this method is never called.
在低内存条件下不再清除视图,因此永远不会调用此方法。
Therefore, you do notwant to move the setting of your IBOutlet
references to nil
anywhere, because the views are no longer purged. It would make no sense to set them to nil
in didReceiveMemoryWarning
or anything like that.
因此,你不想要移动的设置IBOutlet
来引用nil
任何地方,因为视图不再清除。将它们设置为nil
indidReceiveMemoryWarning
或类似的内容是没有意义的。
But, if you were responding to low memory events by releasing easily-recreated model objects, emptying caches, etc., in viewDidUnload
, then that stuff should definitely move to didReceiveMemoryWarning
. But then, again, most of us already had it there already.
但是,如果您通过释放容易重新创建的模型对象、清空缓存等来响应低内存事件viewDidUnload
,那么这些东西肯定应该移到didReceiveMemoryWarning
. 但话又说回来,我们中的大多数人已经有了它。
Finally, if you free anything in didReceiveMemoryWarning
, just make sure your code doesn't rely upon them being recreated in viewDidLoad
again when you pop back, because that will not be called (since the view, itself, was never unloaded).
最后,如果您在 中释放了任何内容didReceiveMemoryWarning
,请确保您的代码viewDidLoad
在您弹回时不会依赖于它们再次被重新创建,因为它不会被调用(因为视图本身从未被卸载)。
As applefreak says, it depends upon what you were doing in viewDidUnload
. If you update your question with explicit examples of what you had in your viewDidUnload
, we can probably provide less abstract counsel.
正如 applefreak 所说,这取决于你在viewDidUnload
. 如果您用明确的例子来更新您的问题viewDidUnload
,我们可能会提供不那么抽象的建议。
回答by auco
The short answer:
简短的回答:
Never use -didReceiveMemoryWarning for a balanced tear down as it might get called never or multiple times. If you have your setup in -viewDidLoad, place your cleanup code in -dealloc.
切勿使用 -didReceiveMemoryWarning 进行平衡拆除,因为它可能永远不会或多次被调用。如果您在 -viewDidLoad 中有您的设置,请将您的清理代码放在 -dealloc 中。
The long answer:
长答案:
It's not easy to give a general answer, as it really depends on the situation. However, there are two important facts to state:
给出一个笼统的答案并不容易,因为这实际上取决于具体情况。但是,有两个重要的事实需要说明:
1. -viewDidUnload is deprecated and in fact never called starting with iOS6 and later. So, if you have your cleanup code in there, your app leaks under these OS versions
1. -viewDidUnload 已弃用,实际上从 iOS6 及更高版本开始从未调用过。所以,如果你有清理代码,你的应用程序会在这些操作系统版本下泄漏
2. -didReceiveMemoryWarning might be called multiple times or never. So it's a really bad place for a balanced teardown of objects you created somewhere else
2. -didReceiveMemoryWarning 可能会被多次调用,也可能永远不会被调用。因此,对于您在其他地方创建的对象的平衡拆解来说,这是一个非常糟糕的地方
My answer is looking at the common case where you are using properties, for example:
我的答案是查看您使用属性的常见情况,例如:
@property (strong) UIView *myCustomView // <-- this is what I'm talking about
@property (assign) id *myDelegate
Here you have to do some cleanup, because you either created and own the customView or InterfaceBuilder created it, but you are retaining it. Before iOS 6 you would probably have done something like this:
在这里,您必须进行一些清理,因为您创建并拥有 customView 或 InterfaceBuilder 创建它,但您正在保留它。在 iOS 6 之前,你可能会做这样的事情:
- (void)viewDidLoad {
self.myCustomView = [[UIView alloc] initWithFrame:…];
}
- (void)viewDidUnload { // <-- deprecated!
[myCustomView removeFromSuperView];
self.myCustomView = nil;
}
...because (again) myCustomView
is a retained property, created and owned by you and so you have to take care and "release" it (set it to nil) at the end.
...因为(再次)myCustomView
是保留财产,由您创建和拥有,因此您必须小心并在最后“释放”它(将其设置为 nil)。
With iOS 6, the best place to replace -viewDidUnload
and to set the retained property to nil is probably -dealloc
. There's also viewWillAppear
and viewDidDisappear
, but these are not tied to the lifecycle of your view/controller, but the display cycle (On the other hand, the -...appear methods are perfect for un-/registering notification listeners!). So it might not be appropriate to create and destroy views before and after every display. dealloc
is the only method we can be sure of to be called at the very end of the controller's lifecycle. Note that you must not call [super dealloc]
if you're using ARC:
对于 iOS 6,替换-viewDidUnload
和设置保留属性为 nil的最佳位置可能是-dealloc
. 还有viewWillAppear
and viewDidDisappear
,但它们与视图/控制器的生命周期无关,而是与显示周期相关(另一方面, -...appear 方法非常适合取消/注册通知侦听器!)。因此,在每次显示之前和之后创建和销毁视图可能并不合适。dealloc
是我们可以确定在控制器生命周期结束时调用的唯一方法。请注意,[super dealloc]
如果您使用的是 ARC,则不得调用:
- (void)dealloc {
self.myCustomView = nil;
}
However, if you're using viewDidLoad
to do some view related setup that can be freed upon low memory conditions, the other posts showing how to deal with low memory situations are totally valid. In this case you can also use dealloc, but you have to check if your views are still there.
但是,如果您正在使用viewDidLoad
一些可以在低内存情况下释放的与视图相关的设置,则显示如何处理低内存情况的其他帖子是完全有效的。在这种情况下,您也可以使用 dealloc,但您必须检查您的视图是否仍然存在。
The Lifecycle of a ViewController
ViewController 的生命周期
Maybe it's also helpful to look a the general lifecycle of a ViewController:
也许查看 ViewController 的一般生命周期也有帮助:
This is the lifetime of a viewController (lines in italic mean that these methods might be called multiple times):
这是 viewController 的生命周期(斜体表示这些方法可能会被多次调用):
- init: ViewController loaded, no interface element (IBOutlet) available yet (all nil)
- viewDidLoad: the nib/storyboard has been loaded and all objects are available. The user sees nothing yet
- viewWillAppear: the view is about to be displayed
- viewDidAppear: the view is on screen
- viewWillDisappear: the view is about to go away
- viewDidDisappear: the view just was taken off the window
- viewDidUnload: NEVER CALLED in iOS6/7
- didReceiveMemoryWarning: You don't know if, when and how often this is called. Prior to iOS6 it might unload the view, after iOS6 it just purges an offscreen cache or does nothing
- dealloc: the viewController is about to get destroyed
- init: ViewController 已加载,尚无可用的界面元素 (IBOutlet)(全部为零)
- viewDidLoad:笔尖/故事板已加载,所有对象都可用。用户什么也看不到
- viewWillAppear:视图即将显示
- viewDidAppear:视图在屏幕上
- viewWillDisappear:视图即将消失
- viewDidDisappear:视图刚从窗口中取出
- viewDidUnload:在 iOS6/7 中从未调用
- didReceiveMemoryWarning:您不知道是否、何时以及多久调用一次。在 iOS6 之前它可能会卸载视图,在 iOS6 之后它只是清除屏幕外缓存或什么都不做
- dealloc:viewController 即将被销毁
So, to sum it up there are various possibilities; what goes where now really depends on what was initialized where:
所以,总结起来有各种可能性;现在去哪里实际上取决于初始化的位置:
- -dealloc if created in -init: or -viewDidLoad:
- -viewWill/DidDisappear (paired with -viewWill/DidAppear)
- -didReceiveMemoryWarning (might or might not be called)
- -dealloc 如果在 -init: 或 -viewDidLoad: 中创建:
- -viewWill/DidDisappear(与 -viewWill/DidAppear 配对)
- -didReceiveMemoryWarning(可能会或可能不会被调用)
回答by Jonas
If you need to know if your UIViewController is dismissing you can add this code to your viewWillDisappear:
如果您需要知道您的 UIViewController 是否正在关闭,您可以将此代码添加到您的 viewWillDisappear 中:
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if ([self isBeingDismissed] || [self isMovingFromParentViewController])
{
// Do your viewDidUnload stuff
}
}
It is not called at the same time as viewDidUnload did once in the view controller life cycle, but works in most cases for your needs!
它不会与 viewDidUnload 在视图控制器生命周期中同时调用一次,但在大多数情况下都可以满足您的需求!
回答by applefreak
回答by neelamc23
In most typical cases, this method can be used in place of the old viewDidUnload.
在大多数典型情况下,可以使用此方法代替旧的 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 syntax:
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)
}