想要了解 iOS UIViewController 生命周期
您能解释一下管理 UIViewController
生命周期的正确方法吗?
我特别想知道如何使用 Initialize
、ViewDidLoad
、ViewWillAppear
、ViewDidAppear
、Mono Touch 中
、UIViewController
类的 ViewWillDisappearViewDidDisappear
、ViewDidUnload
和 Dispose
方法。
Could you explain me the correct manner to manage the UIViewController
lifecycle?
In particular, I would like to know how to use Initialize
, ViewDidLoad
, ViewWillAppear
, ViewDidAppear
, ViewWillDisappear
, ViewDidDisappear
, ViewDidUnload
and Dispose
methods in Mono Touch for a UIViewController
class.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
当您加载/显示/隐藏视图控制器时,所有这些命令都会由 iOS 在适当的时间自动调用。需要注意的是,这些方法附加到
UIViewController
而不是UIView
本身。仅使用UIView
您无法获得任何这些功能。Apple 网站此处提供了很棒的文档。简单地说:
ViewDidLoad
- 在创建类并从 xib 加载时调用。非常适合初始设置和一次性工作。ViewWillAppear
- 在视图出现之前调用,适用于隐藏/显示字段或您希望每次在视图可见之前发生的任何操作。因为您可能会在视图之间来回切换,所以每次视图即将出现在屏幕上时都会调用此函数。ViewDidAppear
- 在视图出现后调用 - 启动动画或从 API 加载外部数据的好地方。ViewWillDisappear
/DidDisappear
- 与ViewWillAppear
/ViewDidAppear
相同。ViewDidUnload
/ViewDidDispose
- 在 Objective-C 中,这是你清理和释放东西的地方,但这是自动处理的,所以你实际上不需要做太多需要在这里做。All these commands are called automatically at the appropriate times by iOS when you load/present/hide the view controller. It's important to note that these methods are attached to
UIViewController
and not toUIView
s themselves. You won't get any of these features just using aUIView
.There's great documentation on Apple's site here. Putting in simply though:
ViewDidLoad
- Called when you create the class and load from xib. Great for initial setup and one-time-only work.ViewWillAppear
- Called right before your view appears, good for hiding/showing fields or any operations that you want to happen every time before the view is visible. Because you might be going back and forth between views, this will be called every time your view is about to appear on the screen.ViewDidAppear
- Called after the view appears - great place to start an animations or the loading of external data from an API.ViewWillDisappear
/DidDisappear
- Same idea asViewWillAppear
/ViewDidAppear
.ViewDidUnload
/ViewDidDispose
- In Objective-C, this is where you do your clean-up and release of stuff, but this is handled automatically so not much you really need to do here.更新:ViewDidUnload 在 iOS 6 中已被弃用,因此相应地更新了答案。
UIViewController 生命周期如下图所示:
使用 Xamarin Native/Mono Touch 的优点是,它使用本机 API,因此它遵循与 Apple 文档中相同的 ViewController 生命周期。
UPDATE: ViewDidUnload was deprecated in iOS 6, so updated the answer accordingly.
The UIViewController lifecycle is diagrammed here:
The advantage of using Xamarin Native/Mono Touch, is that it uses the native APIs, and so it follows the same ViewController lifecycle as you would find in Apple's Documentation.
这适用于最新的 iOS 版本(使用 Xcode 9.3、Swift 4.1 修改)。以下是完成
UIViewController
生命周期的所有阶段。loadView()
loadViewIfNeeded()
viewDidLoad()
viewWillAppear(_animated: Bool)
viewWillLayoutSubviews()
viewDidLayoutSubviews ()
viewDidAppear(_animated: Bool)
viewWillDisappear(_animated: Bool)
viewDidDisappear(_animated ) : Bool)
让我解释一下所有这些阶段。
1.
loadView
此事件创建/加载控制器管理的视图。如果找到 null,它可以从关联的 nib 文件或空
UIView
加载。这使得它成为以编程方式在代码中创建视图的好地方。
2.
loadViewIfNeeded
如果当前
viewController
的视图尚未设置,则此方法将加载视图,但请记住,这仅在 iOS 中可用 >= 9.0。因此,如果您支持 iOS <9.0,则不要指望它会出现。3.
viewDidLoad
viewDidLoad
事件仅在创建视图并将其加载到内存中但尚未定义视图边界时调用。这是初始化视图控制器将要使用的对象的好地方。4.
viewWillAppear
每当视图出现在屏幕上时,此事件都会通知
viewController
。在此步骤中,视图已定义边界,但未设置方向。5.
viewWillLayoutSubviews
这是生命周期中最终确定边界的第一步。如果您不使用约束或自动布局,您可能想在此处更新子视图。此功能仅适用于 iOS >=5.0。因此,如果您支持 iOS <5.0,则不要指望它会出现。
6.
viewDidLayoutSubviews
此事件通知视图控制器子视图已设置。这是在子视图设置后对其进行任何更改的好地方。此功能仅适用于 iOS >=5.0。因此,如果您支持 iOS <5.0,则不要指望它会出现。
7.
viewDidAppear
viewDidAppear
事件在视图呈现在屏幕上后触发。这使得它成为从后端服务或数据库获取数据的好地方。8。
viewWillDisappear
当呈现的
viewController
视图即将消失、解除、覆盖或隐藏在其他后面时,
。这是一个好地方,您可以在其中限制网络调用、使计时器无效或释放绑定到该 viewController 的对象。viewWillDisappear
事件会触发>视图控制器9.
viewDidDisappear
这是生命周期的最后一步,任何人都可以处理,因为在呈现的
viewController
视图消失、解除、覆盖或隐。现在,根据 Apple,当您实现此方法时,您应该记住调用该特定方法的
super
实现。希望这有帮助。
谢谢。
更新 - 正如 @ThomasW 在注释中指出的那样,
viewWillLayoutSubviews
和viewDidLayoutSubviews
也会在加载主视图的子视图时调用,例如当加载表视图或集合视图的单元格时。更新 - 正如 @Maria 在评论中指出的那样,
loadView
的描述已更新This is for latest iOS Versions(Modified with Xcode 9.3, Swift 4.1). Below are all the stages which makes the lifecycle of a
UIViewController
complete.loadView()
loadViewIfNeeded()
viewDidLoad()
viewWillAppear(_ animated: Bool)
viewWillLayoutSubviews()
viewDidLayoutSubviews()
viewDidAppear(_ animated: Bool)
viewWillDisappear(_ animated: Bool)
viewDidDisappear(_ animated: Bool)
Let me explain all those stages.
1.
loadView
This event creates/loads the view that the controller manages. It can load from an associated nib file or an empty
UIView
if null was found.This makes it a good place to create your views in code programmatically.
2.
loadViewIfNeeded
If incase the view of current
viewController
has not been set yet then this method will load the view but remember, this is only available in iOS >=9.0. So if you are supporting iOS <9.0 then don't expect it to come into the picture.3.
viewDidLoad
The
viewDidLoad
event is only called when the view is created and loaded into memory but the bounds for the view are not defined yet. This is a good place to initialise the objects that the view controller is going to use.4.
viewWillAppear
This event notifies the
viewController
whenever the view appears on the screen. In this step the view has bounds that are defined but the orientation is not set.5.
viewWillLayoutSubviews
This is the first step in the lifecycle where the bounds are finalised. If you are not using constraints or Auto Layout you probably want to update the subviews here. This is only available in iOS >=5.0. So if you are supporting iOS <5.0 then don't expect it to come into the picture.
6.
viewDidLayoutSubviews
This event notifies the view controller that the subviews have been setup. It is a good place to make any changes to the subviews after they have been set. This is only available in iOS >=5.0. So if you are supporting iOS <5.0 then don't expect it to come into the picture.
7.
viewDidAppear
The
viewDidAppear
event fires after the view is presented on the screen. Which makes it a good place to get data from a backend service or database.8.
viewWillDisappear
The
viewWillDisappear
event fires when the view of presentedviewController
is about to disappear, dismiss, cover or hide behind otherviewController
. This is a good place where you can restrict your network calls, invalidate timer or release objects which is bound to thatviewController
.9.
viewDidDisappear
This is the last step of the lifecycle that anyone can address as this event fires just after the view of presented
viewController
has been disappeared, dismissed, covered or hidden.Now as per Apple when you are implementing this methods you should remember to call
super
implementation of that specific method.Hope this helped.
Thanks.
UPDATE - As @ThomasW pointed inside comment
viewWillLayoutSubviews
andviewDidLayoutSubviews
will also be called at other times when subviews of the main view are loaded, for example when cells of a table view or collection view are loaded.UPDATE - As @Maria pointed inside comment, description of
loadView
was updatediOS 10,11 (Swift 3.1,Swift 4.0)
根据
UIKit
UIViewController > 开发人员,1。 loadView()
如果子类不使用 笔尖。永远不应该直接调用。
2. loadViewIfNeeded()
加载视图控制器的视图(如果尚未设置)。
3. viewDidLoad()
在视图加载后调用。对于在代码中创建的视图控制器,这是在 -loadView 之后。对于从笔尖取消归档的视图控制器,这是在设置视图之后。
4. viewWillAppear(_animated: Bool)
当视图即将变得可见时调用。默认不执行任何操作
5。 viewWillLayoutSubviews()
在调用视图控制器的视图的layoutSubviews 方法之前调用。子类可以根据需要实现。默认不执行任何操作。
6. viewDidLayoutSubviews()
在调用视图控制器的视图的layoutSubviews方法后调用。子类可以根据需要实现。默认不执行任何操作。
7. viewDidAppear(_animated: Bool)
当视图完全转换到屏幕上时调用。默认不执行任何操作
8。 viewWillDisappear(_animated: Bool)
当视图被关闭、覆盖或以其他方式隐藏时调用。默认不执行任何操作
9。 viewDidDisappear(_animated: Bool)
在视图被解除、覆盖或以其他方式隐藏后调用。默认不执行任何操作
10。 viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
当视图转换时调用。
11. willMove(toParentViewController 父级:UIViewController?)
12. didMove(toParentViewController Parent: UIViewController?)
这两个方法是公共的,供容器子类在子控制器之间转换时调用。如果它们被覆盖,覆盖应确保调用 super。
当从父级中删除子级时,这两个方法中的父级参数均为 nil;否则它等于新的父视图控制器。
13. didReceiveMemoryWarning()
当父应用程序收到内存警告时调用。在 iOS 6.0 上,默认情况下将不再清除视图。
iOS 10,11 (Swift 3.1,Swift 4.0)
According to
UIViewController
inUIKit
developers,1. loadView()
This is where subclasses should create their custom view hierarchy if they aren't using a nib. Should never be called directly.
2. loadViewIfNeeded()
Loads the view controller's view if it has not already been set.
3. viewDidLoad()
Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set.
4. viewWillAppear(_ animated: Bool)
Called when the view is about to made visible. Default does nothing
5. viewWillLayoutSubviews()
Called just before the view controller's view's layoutSubviews method is invoked. Subclasses can implement as necessary. Default does nothing.
6. viewDidLayoutSubviews()
Called just after the view controller's view's layoutSubviews method is invoked. Subclasses can implement as necessary. Default does nothing.
7. viewDidAppear(_ animated: Bool)
Called when the view has been fully transitioned onto the screen. Default does nothing
8. viewWillDisappear(_ animated: Bool)
Called when the view is dismissed, covered or otherwise hidden. Default does nothing
9. viewDidDisappear(_ animated: Bool)
Called after the view was dismissed, covered or otherwise hidden. Default does nothing
10. viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
Called when the view is Transitioning.
11. willMove(toParentViewController parent: UIViewController?)
12. didMove(toParentViewController parent: UIViewController?)
These two methods are public for container subclasses to call when transitioning between child controllers. If they are overridden, the overrides should ensure to call the super.
The parent argument in both of these methods is nil when a child is being removed from its parent; otherwise it is equal to the new parent view controller.
13. didReceiveMemoryWarning()
Called when the parent application receives a memory warning. On iOS 6.0 it will no longer clear the view by default.
从 iOS 6 及更高版本开始。新图如下:
As of iOS 6 and onward. The new diagram is as follows:
让我们关注负责 UIViewController 生命周期的方法:
<强>创作:
- (void)init
- (void)initWithNibName:
视图创建:
- (BOOL)isViewLoaded
- (void)loadView
- (void)viewDidLoad
- (UIView *)initWithFrame:(CGRect)frame
- (UIView *)initWithCoder:(NSCoder *)coder
处理视图状态更改:
- (void)viewDidLoad
- (void)viewWillAppear:(BOOL)动画
- (void)viewDidAppear:(BOOL)动画
- (void)viewWillDisappear:(BOOL)动画
- (void)viewDidDisappear:(BOOL)动画
- (void)viewDidUnload
内存警告处理:
- (void)didReceiveMemoryWarning
释放< /strong>
- (void)viewDidUnload
- (void)dealloc
有关更多信息,请查看 UIViewController 类参考。
Let's concentrate on methods, which are responsible for the UIViewController's lifecycle:
Creation:
- (void)init
- (void)initWithNibName:
View creation:
- (BOOL)isViewLoaded
- (void)loadView
- (void)viewDidLoad
- (UIView *)initWithFrame:(CGRect)frame
- (UIView *)initWithCoder:(NSCoder *)coder
Handling of view state changing:
- (void)viewDidLoad
- (void)viewWillAppear:(BOOL)animated
- (void)viewDidAppear:(BOOL)animated
- (void)viewWillDisappear:(BOOL)animated
- (void)viewDidDisappear:(BOOL)animated
- (void)viewDidUnload
Memory warning handling:
- (void)didReceiveMemoryWarning
Deallocation
- (void)viewDidUnload
- (void)dealloc
For more information please take a look on UIViewController Class Reference.
图中未提及
viewWillLayoutSubviews
和viewDidLayoutSubviews
方法,但它们是在viewWillAppear
和viewDidAppear
之间调用的。它们可以被多次调用。The methods
viewWillLayoutSubviews
andviewDidLayoutSubviews
aren't mentioned in the diagrams, but these are called betweenviewWillAppear
andviewDidAppear
. They can be called multiple times.Haider 的答案对于 iOS 6 之前的版本是正确的。但是,从 iOS 6 开始,viewDidUnload 和 viewWillUnload 永远不会被调用。 文档 状态:“在内存不足的情况下不再清除视图,因此永远不会调用此方法。”
Haider's answer is correct for pre-iOS 6. However, as of iOS 6 viewDidUnload and viewWillUnload are never called. The docs state: "Views are no longer purged under low-memory conditions and so this method is never called."
这里有很多过时且不完整的信息。仅适用于 iOS 6 及更高版本:
loadView
[a]viewDidLoad
[a]viewWillAppear
viewWillLayoutSubviews
是第一次确定边界viewDidLayoutSubviews
viewDidAppear
*
viewWillLayoutSubviews
[b]*
viewDidLayoutSubviews
[b]脚注:
<子>
(a) - 如果您在
didReceiveMemoryWarning
期间手动清空视图,loadView
和viewDidLoad
将再次调用。也就是说,默认情况下,每个视图控制器实例仅调用loadView
和viewDidLoad
一次。<子>
(b) 可能会被额外叫0次或更多次。
There's a lot of outdated and incomplete information here. For iOS 6 and newer only:
loadView
[a]viewDidLoad
[a]viewWillAppear
viewWillLayoutSubviews
is the first time bounds are finalizedviewDidLayoutSubviews
viewDidAppear
*
viewWillLayoutSubviews
[b]*
viewDidLayoutSubviews
[b]Footnotes:
(a) - If you manually nil out your view during
didReceiveMemoryWarning
,loadView
andviewDidLoad
will be called again. That is, by defaultloadView
andviewDidLoad
only gets called once per view controller instance.(b) May be called an additional 0 or more times.
官方文档中解释状态转换: https:// developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/index.html
此图显示了各种视图“will”和“did”回调方法之间的有效状态转换
有效状态转换:
取自: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Art/UIViewController类Reference_2x.png
Explaining State Transitions in the official doc: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/index.html
This image shows the valid state transitions between various view ‘will’ and ‘did’ callback methods
Valid State Transitions:
Taken from: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Art/UIViewController Class Reference_2x.png
根据 Apple 文档 — 开始开发 iOS 应用程序 (Swift)
— 使用视图控制器 — 了解视图控制器生命周期
As per Apple's doc — Start Developing iOS Apps (Swift)
— Work with View Controllers — Understand the View Controller Lifecycle