您能解释一下管理UIViewController
生命周期的正确方法吗?
特别是,我想知道如何使用Initialize
,ViewDidLoad
,ViewWillAppear
,ViewDidAppear
,ViewWillDisappear
,ViewDidDisappear
, {/ 1}}类的Mono Touch中的ViewDidUnload
和Dispose
方法。
答案 0 :(得分:395)
答案 1 :(得分:383)
当您加载/显示/隐藏视图控制器时,iOS会在适当的时间自动调用所有这些命令。重要的是要注意,这些方法附加到UIViewController
而不是UIView
本身。仅使用UIView
,您将无法获得任何这些功能。
Apple的网站here上有很好的文档。简单地说:
ViewDidLoad
- 在创建类并从xib加载时调用。非常适合初始设置和一次性工作。
ViewWillAppear
- 在您的视图出现之前调用,适用于隐藏/显示字段或您希望每次在视图可见之前发生的任何操作。由于您可能会在视图之间来回切换,因此每次您的视图即将出现在屏幕上时都会调用此视图。
ViewDidAppear
- 在视图显示后调用 - 开始制作动画或从API加载外部数据的好地方。
ViewWillDisappear
/ DidDisappear
- 与ViewWillAppear
/ ViewDidAppear
相同的想法。
ViewDidUnload
/ ViewDidDispose
- 在Objective-C中,这是你清理和发布内容的地方,但这是自动处理的,所以你真的不需要做什么这里。
答案 2 :(得分:142)
这适用于最新的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
强>
此事件创建控制器管理的视图。仅在以编程方式创建视图控制器时调用它。这使它成为在代码中创建视图的好地方。
如果子类没有使用nib,那么子类应该创建自定义视图层次结构。 永远不应该直接打电话。
<强> 2。 loadViewIfNeeded
强>
如果尚未设置当前viewController
的视图,则此方法将加载视图但请记住,这仅适用于iOS&gt; = 9.0。因此,如果您支持iOS&lt; 9.0,那么请不要期望它出现在图片中。
加载视图控制器的视图(如果尚未设置)。
第3。 viewDidLoad
强>
仅在创建视图并将其加载到内存中时调用viewDidLoad
事件,但尚未定义视图的边界。这是初始化视图控制器将要使用的对象的好地方。
加载视图后调用。对于在代码中创建的视图控制器,这是在-loadView之后。 对于从笔尖取消归档的视图控制器,这是在设置视图之后。
<强> 4。 viewWillAppear
只要视图出现在屏幕上,此事件就会通知viewController
。在此步骤中,视图具有已定义的边界,但未设置方向。
视图即将显示时调用。默认不做任何事。
<强> 5。 viewWillLayoutSubviews
强>
这是生命周期中最终确定边界的第一步。如果您没有使用约束或自动布局,则可能需要在此处更新子视图。这仅适用于iOS&gt; = 5.0。因此,如果您支持iOS&lt; 5.0,那么请不要期望它出现在图片中。
在调用视图控制器视图的layoutSubviews方法之前调用。 子类可以根据需要实现。默认值为nop。
<强> 6。 viewDidLayoutSubviews
强>
此事件通知视图控制器已设置子视图。它是设置后对子视图进行任何更改的好地方。这仅适用于iOS&gt; = 5.0。因此,如果您支持iOS&lt; 5.0,那么请不要期望它出现在图片中。
在调用视图控制器的视图后调用layoutSubviews方法。 子类可以根据需要实现。默认值为nop。
<强> 7。 viewDidAppear
强>
在屏幕上显示视图后,viewDidAppear
事件将触发。这使它成为从后端服务或数据库获取数据的好地方。
视图完全转换到屏幕时调用。 默认不执行任何操作
<强> 8。 viewWillDisappear
强>
当呈现的viewWillDisappear
视图即将消失,解散,覆盖或隐藏在其他viewController
后面时,viewController
事件将触发。这是一个可以限制网络呼叫,使计时器无效或释放绑定到viewController
的对象的好地方。
视图被解除,覆盖或隐藏时调用。
<强> 9。 viewDidDisappear
强>
这是生命周期的最后一步,任何人都可以解决,因为此事件在呈现viewController
的视图消失,解散,覆盖或隐藏之后才会触发。
视图被删除,覆盖或以其他方式隐藏后被调用。 默认不执行任何操作
现在,根据 Apple ,当您实施此方法时,您应该记得调用super
实施该特定方法。
如果你是UIViewController的子类,你必须调用这个方法的超级实现,即使你没有使用NIB。 (为方便起见,默认的init方法将为您执行此操作,并为这两个方法参数指定nil。)在指定的NIB中,File的所有者代理应将其类设置为视图控制器子类,视图插座连接到主视图。如果使用nil nib名称调用此方法,则此类&#39;
-loadView
方法将尝试加载名称与视图控制器类相同的NIB。如果事实上不存在此类NIB,则必须在调用-setView:
之前调用-view
,或覆盖-loadView
方法以编程方式设置视图。
希望这有帮助。 感谢。
更新 - 正如@ThomasW指向内部评论viewWillLayoutSubviews
和viewDidLayoutSubviews
也将在其他时间加载主视图的子视图时调用,例如当加载了表视图或集合视图。
答案 3 :(得分:39)
iOS 10,11 (Swift 3.1,Swift 4.0)
根据UIViewController
开发人员中的UIKit
,
<强> 1。的loadView()强>
如果子类不使用nib,那么子类应创建自定义视图层次结构。永远不应该直接打电话。
<强> 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(大小:CGSize,带协调器:UIViewControllerTransitionCoordinator)
视图正在转换时调用。
<强> 11。 willMove(toParentViewController parent:UIViewController?)
<强> 12。 didMove(toParentViewController parent:UIViewController?)
这两个方法对于在子控制器之间转换时要调用的容器子类是公共的。如果它们被覆盖,则覆盖应确保调用超级。
当从子组中删除子项时,这两种方法中的父参数都是nil;否则它等于新的父视图控制器。
<强> 13。 didReceiveMemoryWarning()强>
当父应用程序收到内存警告时调用。在iOS 6.0上,默认情况下它将不再清除视图。
答案 4 :(得分:28)
iOS 6及更高版本。新图如下:
答案 5 :(得分:19)
图表中未提及方法viewWillLayoutSubviews
和viewDidLayoutSubviews
,但这些方法在viewWillAppear
和viewDidAppear
之间调用。它们可以被多次调用。
答案 6 :(得分:18)
让我们专注于负责UIViewController's生命周期的方法:
<强>创作:强>
- (void)init
- (void)initWithNibName:
查看创建:
- (BOOL)isViewLoaded
- (void)loadView
- (void)viewDidLoad
- (UIView *)initWithFrame:(CGRect)frame
- (UIView *)initWithCoder:(NSCoder *)coder
处理视图状态更改:
- (void)viewDidLoad
- (void)viewWillAppear:(BOOL)animated
- (void)viewDidAppear:(BOOL)animated
- (void)viewWillDisappear:(BOOL)animated
- (void)viewDidDisappear:(BOOL)animated
- (void)viewDidUnload
内存警告处理:
- (void)didReceiveMemoryWarning
<强>取消分配强>
- (void)viewDidUnload
- (void)dealloc
有关详细信息,请查看UIViewController Class Reference。
答案 7 :(得分:16)
Haider的答案对于iOS 6之前是正确的。但是,从iOS 6开始,viewDidUnload和viewWillUnload永远不会被调用。 docs状态:&#34;视图不再在低内存条件下被清除,因此永远不会调用此方法。&#34;
答案 8 :(得分:16)
这里有很多过时和不完整的信息。仅适用于 iOS 6及更高版本:
loadView
并[a] viewDidLoad
并[a] viewWillAppear
viewWillLayoutSubviews
是第一次完成边界viewDidLayoutSubviews
viewDidAppear
*
viewWillLayoutSubviews
[b] *
viewDidLayoutSubviews
[b] <子> 的脚注:强> 子>
<子>
(a) - 如果您在didReceiveMemoryWarning
期间手动忽略视图,则会再次调用loadView
和viewDidLoad
。也就是说,默认情况下loadView
和viewDidLoad
仅在每个视图控制器实例中调用一次。
子>
<子> (b)可称为额外 0 或更多次。 子>
答案 9 :(得分:10)
在官方文档中解释状态转换: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 Class Reference_2x.png
答案 10 :(得分:0)
viewDidLoad()
- 在视图控制器的内容视图(其视图层次结构的顶部)创建并从故事板加载时调用。 ... 使用此方法执行视图控制器所需的任何其他设置。
viewWillAppear()
- 在视图控制器的内容视图添加到应用程序的视图层次结构之前调用。使用此方法可以触发在屏幕上显示内容视图之前需要执行的任何操作
viewDidAppear()
- 在视图控制器的内容视图添加到应用程序的视图层次结构后调用。使用此方法可以在屏幕上显示视图时立即触发任何需要执行的操作,例如获取数据或显示动画。
viewWillDisappear()
- 在视图控制器的内容视图从应用程序的视图层次结构中删除之前调用。使用此方法执行清除任务,例如提交更改或重新签署第一响应者状态。
viewDidDisappear()
- 在视图控制器的内容视图已从应用程序的视图层次结构中删除之后调用。使用此方法执行其他拆卸活动。