您能为我解释管理UIViewController生命周期的正确方法吗?

我特别想知道如何在Mono中使用InitializeViewDidLoadViewWillAppearViewDidAppearViewWillDisappearViewDidDisappearViewDidUnloadDispose方法触摸以获取UIViewController类别。

评论

OSX ViewController和WindowController是否有某些信息或链接?请分享。

#1 楼

当您加载/显示/隐藏视图控制器时,iOS将在适当的时候自动调用所有这些命令。重要的是要注意,这些方法是附加到UIViewController而不是UIView本身的。仅使用UIView就不会获得任何这些功能。

Apple网站上的大量文档都在这里。简单地放入:


ViewDidLoad-创建类并从xib加载时调用。
ViewWillAppear-在视图出现之前立即调用,非常适合隐藏/显示字段或您希望在视图可见之前每次进行的任何操作。因为您可能在视图之间来回移动,所以每次视图将出现在屏幕上时都会调用此方法。
ViewDidAppear-在视图出现后调用-是开始动画或加载外部图像的好地方来自API的数据。
ViewWillDisappear / DidDisappear-与ViewWillAppear / ViewDidAppear相同。
ViewDidUnload / ViewDidDispose-在Objective-C中,这是您清理和释放内容的地方,但这是自动处理,因此您实际上不需要在这里做很多。


评论


该文本有些误导,因为不应将ViewDidLoad用于一次性工作。如果由于内存不足而卸载视图,然后再次加载,则可能会多次调用它。

– Ricky Helgesson
2012年8月20日14:59

创建/初始化视图控制器时,实际上不会调用ViewDidLoad。这是您第一次执行与视图控制器的视图相关的任何视图。就像将其添加为子视图,设置框架等。从笔尖加载时也当然会调用它。

–杰森·格兰德利(Jason Grandelli)
13-10-16在13:43



ViewDidAppear-在视图出现后调用-是开始动画或从API加载外部数据的好地方。为什么是开始加载数据的好地方?为什么不使用viewDidLoad?

–安东·奇金(Anton Chikin)
2014年8月3日,下午5:19

那么关于loadView方法,如果第一次调用某个笔尖时是否在viewDidLoad之前将其加载到内存中,该方法如何。

– iHulk
2014年9月20日在8:09

@chakrit这是一个好点-viewDidAppear是刷新数据的好地方(如果需要)。我不同意KVO,因为它会导致用户从未真正查看过的视图发生不必要的刷新。

–安东·奇金(Anton Chikin)
2014年12月5日下午4:22

#2 楼

更新:ViewDidUnload在iOS 6中已弃用,因此相应地更新了答案。

UIViewController生命周期的图示如下:



使用Xamarin Native / Mono Touch的原因在于它使用了本机API,因此它遵循与Apple文档中相同的ViewController生命周期。

评论


在此流程图中,viewWillLayoutSubviews和viewDidLayoutSubviews在哪里?

–Max_Power89
2014年12月18日下午16:40

该图不准确。自iOS6起不推荐使用viewDidUnload:stackoverflow.com/questions/12509102/…

– occulus
15年4月20日在15:13

这确实是错误的。随着时间的流逝,SO上一个完全错误的答案的另一个例子。计算是高度静态的。

–法蒂
19/09/13在14:02

#3 楼

这是针对最新的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加载。
这使它成为了以编程方式在代码中创建视图的好地方。


如果子类不使用笔尖,则应在此处创建其自定义视图层次结构。
切勿直接调用。
仅当以编程方式创建视图并将根视图分配给view属性时才覆盖此方法。
覆盖时不调用super方法。
loadView


2。 loadViewIfNeeded

如果尚未设置当前viewController的视图,则此方法将加载视图,但请记住,仅在iOS> = 9.0中可用。因此,如果您支持iOS <9.0,那么不要期望它出现在图片中。


如果尚未设置视图控制器的视图,则将其加载。


3。 viewDidLoad

仅当创建视图并将其加载到内存后才调用viewDidLoad事件,但尚未定义视图的边界。这是初始化视图控制器将要使用的对象的好地方。


加载视图后调用。对于在代码中创建的视图控制器,此命令位于-loadView之后。
对于从笔尖未归档的视图控制器,此操作在设置视图之后进行。


4。 viewWillAppear

每当视图出现在屏幕上时,此事件就会通知viewController。在此步骤中,视图具有已定义的边界,但未设置方向。


在视图将变为可见时调用。默认不执行任何操作。


5。 viewWillLayoutSubviews

这是生命周期中确定边界的第一步。如果您没有使用约束或自动版式,则可能要在此处更新子视图。仅在iOS> = 5.0中可用。因此,如果您支持iOS <5.0,那么不要期望它会出现在图片中。


在调用视图控制器的视图的layoutSubviews方法之前调用。
子类可以根据需要实现。默认值为nop。


6。 viewDidLayoutSubviews

此事件通知视图控制器子视图已设置。在设置子视图之后,可以对子视图进行任何更改。仅在iOS> = 5.0中可用。因此,如果您支持iOS <5.0,那么不要期望它出现在图片中。


在调用视图控制器的视图的layoutSubviews方法之后立即调用。
子类可以必要时实施。默认值为nop。


7。 viewDidAppear

屏幕上显示视图后,将触发viewDidAppear事件。这是从后端服务或数据库获取数据的好地方。


当视图完全过渡到屏幕时调用。
默认不执行任何操作


8。 viewWillDisappear

当所呈现的viewWillDisappear的视图即将消失,消失,遮盖或隐藏在其他viewController后面时,将触发viewController事件。在这里,您可以限制网络调用,使计时器无效或释放与该viewController绑定的对象。


在视图被关闭,覆盖或其他隐藏时调用。 br />

9。 viewDidDisappear

这是生命周期的最后一步,任何人都可以解决,因为呈现的viewController的视图已消失,被消除,覆盖或隐藏之后,此事件触发。


解雇,掩盖或以其他方式隐藏。
默认情况下不执行任何操作



现在,按照Apple的方法,在实现此方法时,您应该记住调用该特定方法的super实现。


如果您将UIViewController子类化,则即使您未使用NIB,也必须调用此方法的超级实现。 (为方便起见,默认的init方法将为您执行此操作,并为这两个方法参数都指定nil。)在指定的NIB中,File的Owner代理应将其类设置为您的视图控制器子类,并带有view出口连接到主视图。如果您使用nil nib名称调用此方法,则此类的-loadView方法将尝试加载名称与您的视图控制器类相同的NIB。如果实际上不存在这样的NIB,则必须在调用-setView:之前调用-view,或重写-loadView方法以通过编程方式设置视图。


希望有帮助。
谢谢。

UPDATE-正如@ThomasW指出的那样,注释的viewWillLayoutSubviewsviewDidLayoutSubviews也会在其他时间在加载主视图的子视图时(例如,在加载表视图或集合视图的单元格时)被调用。

更新-@Maria在评论中指出,对loadView的描述已更新

评论


在加载主视图的子视图时(例如,在加载表视图或集合视图的单元格时),viewWillLayoutSubviews和viewDidLayoutSubviews也将在其他时间调用。

– ThomasW
16年4月18日在4:56

这个答案有一个小小的误导:总是调用loadView(),当在IB中创建控制器的视图时,不应覆盖它。

–玛丽亚
18-10-15在6:14

@Maria如果您认为可以改善,请继续编辑答案。谢谢。

– onCompletion
18-10-15在6:19

默认情况下,viewWillAppear viewDidAppear viewDidDisappear不会做错任何事情。您必须在某个时候叫超级。

–米克
18 Dec 6'在0:43在

#4 楼

iOS 10,11(Swift 3.1,Swift 4.0)

根据UIViewController开发人员中的UIKit

1。 loadView()

如果子类不使用笔尖,则应在其中创建其自定义视图层次结构。永远不要直接调用。

2。 loadViewIfNeeded()

如果尚未设置视图控制器的视图,则将其加载。

3。 viewDidLoad()

加载视图后调用。对于用代码创建的视图控制器,该命令位于-loadView之后。对于从笔尖取消存档的视图控制器,这是在设置视图之后。

4。 viewWillAppear(_动画:Bool)

在视图将变为可见时调用。默认不执行任何操作

5。 viewWillLayoutSubviews()

在调用视图控制器的视图的layoutSubviews方法之前调用。子类可以根据需要实现。默认不执行任何操作。

6。 viewDidLayoutSubviews()

在调用视图控制器的视图的layoutSubviews方法之后立即调用。子类可以根据需要实现。默认不执行任何操作。

7。 viewDidAppear(_动画:Bool)

当视图完全过渡到屏幕上时调用。默认不执行任何操作

8。 viewWillDisappear(_动画:Bool)

在视图被关闭,覆盖或其他隐藏时调用。默认不执行任何操作

9。 viewDidDisappear(_动画:Bool)

在视图被取消,覆盖或其他隐藏之后调用。默认不执行任何操作

10。 viewWillTransition(大小:CGSize,带有协调器:UIViewControllerTransitionCoordinator)

在视图转换时调用。

11。 willMove(toParentViewController parent:UIViewController?)

12。 didMove(toParentViewController parent:UIViewController?)

在子控制器之间转换时,这两个方法是公共的,供容器子类调用。如果它们被覆盖,则覆盖应确保调用超级。

从子级中删除子级时,这两种方法中的父级参数均为nil。否则,它等于新的父视图控制器。

13。 didReceiveMemoryWarning()

在父应用程序收到内存警告时调用。在iOS 6.0上,默认情况下将不再清除视图。

评论


确实,stackoverflow不会清除整个线程中所有错误和不完整的答案,这真是很遗憾。就方法调用而言,您的答案似乎是完整的,因此,我将假设您的答案是正确的,然后使用该方法。

–Logicsaurus Rex
17年9月24日在19:16

在loadView下提到的笔尖是什么?

– Petrus Theron
18年7月31日在7:36

@LogicsaurusRex我同意。与SO将问题标记为重复或受保护的方式相同,我认为它应该能够将答案标记为过时或过时

–rmp251
18年8月25日在18:30

上面的第5点是错误的。在ViewController的视图对象调用其layoutSubviews()方法之前,先调用viewWillLayoutSubviews()

–williamukoh
18/12/7在16:32



#5 楼

从iOS 6开始。新图如下:



评论


将该视图称为“ A”。考虑当“ A”消失时出现的第二个视图“ B”。 “ B.viewWillAppear”在“ A.viewDidDisappear”之前还是之后?在任何情况下,这两个顺序会发生变化吗?

–ToolmakerSteve
16 Sep 7'9:20



好像新视图(B)的willApear将在消失之前被调用。对于第二个问题。需要一些时间来研究它。

– Saad
2016年9月8日7:06

#6 楼

让我们专注于负责UIViewController生命周期的方法:



创建:

- (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类参考。

#7 楼

图中未提及方法viewWillLayoutSubviewsviewDidLayoutSubviews,但是在viewWillAppearviewDidAppear之间调用了这些方法。它们可以被多次调用。

评论


在加载主视图的子视图时(例如,在加载表视图或集合视图的单元格时),它们也会在其他时间调用。

– ThomasW
16年4月18日在4:55

#8 楼

Haider的答案对于iOS 6之前的版本是正确的。但是,从iOS 6开始,从未调用过viewDidUnload和viewWillUnload。 docs指出:“不再在低内存条件下清除视图,因此从不调用此方法。”

评论


我试图在ViewWillDisappear,ViewDidDisappear,Dispose中设置断点。但是当我使用PresentViewController()方法进行导航时,没有一个被调用。可能是什么原因 ?

– Sreeraj
2014年12月9日上午10:07

链接不起作用...那么在内存不足的情况下OS会做什么?

–儿子
15年12月2日在10:57

将它们保存到磁盘吗?

–伊恩·沃伯顿(Ian Warburton)
16年8月6日在20:12

#9 楼

这里有很多过时和不完整的信息。仅适用于iOS 6和更高版本:



loadView [a]


viewDidLoad [a]

viewWillAppear

viewWillLayoutSubviews是第一次确定边界
viewDidLayoutSubviews
viewDidAppear

* viewWillLayoutSubviews [b]


* viewDidLayoutSubviews [b]






(a)-如果您手动零在didReceiveMemoryWarning期间退出视图,loadViewviewDidLoad将再次被调用。也就是说,默认情况下,每个视图控制器实例仅调用一次loadViewviewDidLoad




(b)可以再调用0次或多次。


评论


在加载主视图的子视图时(例如,在加载表视图或集合视图的单元格时),viewWillLayoutSubviews和viewDidLayoutSubviews也将在其他时间调用。

– ThomasW
16年4月18日在4:56

#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类Reference_2x.png

#11 楼

按照Apple的文档-开始开发iOS应用(快速)
-使用View Controllers-了解View Controller的生命周期


viewDidLoad()-在View Controller的内容视图(即

使用此方法执行视图控制器所需的任何其他设置。

viewWillAppear() —在之前调用视图控制器的内容视图将添加到应用程序的视图层次结构中。使用此方法可以触发在屏幕上显示内容视图之前需要进行的所有操作。

viewDidAppear()-在将视图控制器的内容视图添加到应用程序的视图层次结构之后立即调用。使用此方法可以触发在屏幕上显示视图后立即进行的所有操作,例如获取数据或显示动画。

viewWillDisappear()-在从视图控制器的内容视图中删除之前调用。应用程序的视图层次结构。使用此方法可以执行清除任务,例如提交更改或退出第一响应者状态。

viewDidDisappear()-在从应用程序的视图层次结构中删除视图控制器的内容视图后立即调用。使用此方法执行其他拆卸活动。