期待了解iOS UIViewController生命周期
你能解释我pipe理UIViewController
生命周期的正确方式吗?
特别是,我想知道如何在Mono Touch中为UIViewController
类使用Initialize
, ViewDidLoad
, ViewWillAppear
, ViewDidAppear
, ViewWillDisappear
, ViewDidDisappear
, ViewDidUnload
和Dispose
方法。
所有这些命令在iOS加载/显示/隐藏视图控制器时都会在适当的时候自动调用。 请注意,这些方法连接到UIViewController
而不是连接到UIView
本身。 你不会使用UIView
获得任何这些function。
苹果公司的网站上有很棒的文档。 简单地说:
-
ViewDidLoad
– 在创build类并从xib载入时调用。 非常适合初始设置和一次性工作。 -
ViewWillAppear
– 在视图出现之前调用,适用于在视图可见之前每次隐藏/显示字段或任何想要发生的操作。 因为您可能会在视图之间来回切换,所以每当您的视图即将出现在屏幕上时,都会调用此视图。 -
ViewDidAppear
– 在视图出现之后调用 – 启动animation或从API加载外部数据的好地方。 -
ViewWillDisappear
/DidDisappear
– 与ViewWillDisappear
/DidDisappear
相同。 -
ViewDidUnload
/ViewDidDispose
– 在Objective C中,这是你清理和释放东西的地方,但这是自动处理的,所以在这里你不需要做太多的事情。
UIViewController生命周期在这里图示:
http://rdkw.wordpress.com/2013/02/24/ios-uiviewcontroller-lifecycle/
这是最新的iOS版本。 主要有六个不同的阶段,使UIViewController的生命周期。 我按照顺序列出了它们。
的loadView
viewDidLoad中
viewWillAppear中
viewWillLayoutSubviews
viewDidLayoutSubviews
viewDidAppear
让我解释所有这些阶段。
- 的loadView
此事件创build控制器pipe理的视图。 只有在以编程方式创build视图控制器时才会调用它。 这使它成为在代码中创build视图的好地方。
- viewDidLoad中
viewDidLoad事件只有在视图被创build并加载到内存时才被调用。 但是这个观点的界限还没有定义。 这是初始化视图控制器将要使用的对象的好地方。
- viewWillAppear中
每当视图出现在屏幕上时,此事件通知视图控制器。 在这个步骤中,视图具有已定义的边界,但未定位方向。
- viewWillLayoutSubviews
这是边界最终确定的生命周期中的第一步。 如果您不使用约束或自动布局,则可能需要在此处更新子视图。
- viewDidLayoutSubviews
此事件通知视图控制器已设置子视图。 设置后,对子视图进行任何更改都是很好的select。
- viewDidAppear
视图出现在屏幕上后,viewDidAppear事件触发。 这使得它成为从后端服务或数据库获取数据的好地方。
希望这有助于。 谢谢。
从iOS 6开始。 新图如下:
Haider的答案在iOS 6之前是正确的。但是从iOS 6开始,viewDidUnload和viewWillUnload永远不会被调用。 文档陈述:“视图不再在低内存条件下清除,所以这个方法从来没有被调用。
viewWillLayoutSubviews
和viewDidLayoutSubviews
方法在图中没有提到,但在viewWillAppear
和viewDidAppear
之间调用。 他们可以被多次调用。
这里有很多过时和不完整的信息。 仅适用于iOS 6和更高版本 :
-
loadView
[a] -
viewDidLoad
[a] -
viewWillAppear
-
viewWillLayoutSubviews
是第一次界定 -
viewDidLayoutSubviews
-
viewDidAppear
-
*
viewWillLayoutSubviews
[b] -
*
viewDidLayoutSubviews
[b]
脚注:
(a) – 如果您在didReceiveMemoryWarning
过程中手动清除了视图,则会再次调用loadView
和viewDidLoad
。 也就是说,默认情况下, loadView
和viewDidLoad
仅在每个视图控制器实例中被调用一次。
(b)可以被称为额外的0次或更多次。
让我们专注于负责UIViewController生命周期的方法:
-
创build:
- (void)init
- (void)initWithNibName:
-
视图创build:
- (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类参考 。
在官方文档中解释状态转换: https : //developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/index.html
该图显示了各种视图'will'和'did'callback方法之间的有效状态转换
iOS 10,11 (Swift 3.1,Swift 4.0)
根据UIKit
开发者的UIViewController
,
1. loadView()
这是子类应该创build自定义视图层次的地方,如果他们不使用笔尖。 不应该直接调用。
2. loadViewIfNeeded()
如果尚未设置,则加载视图控制器的视图。
3. viewDidLoad()
视图加载完成后调用。 对于在代码中创build的视图控制器,这是after-loadView。 对于从笔尖取消存档的视图控制器,这是在视图设置之后。
4. viewWillLayoutSubviews()
在视图控制器视图的layoutSubviews方法被调用之后调用。 子类可以根据需要实现。
5. viewDidLayoutSubviews()
当尺寸,位置和约束条件应用于所有对象时调用。
6. viewWillAppear(_ animated:Bool)
当视图即将显示时调用。 默认什么都不做
7. viewDidAppear(_ animated:Bool)
当视图完全转换到屏幕上时调用。 默认什么都不做
8. viewWillDisappear(_ animated:Bool)
当视图被解散,覆盖或以其他方式隐藏时调用。 默认什么都不做
9. viewDidDisappear(_ animated:Bool )
在视图被解散,覆盖或以其他方式隐藏之后调用。 默认什么都不做
10. viewWillTransition(大小:CGSize,协调器:UIViewControllerTransitionCoordinator)
当视图正在转换时调用。
11. willMove(toParentViewController父:UIViewController?)
12. didMove(toParentViewController父级:UIViewController?)
在子控制器之间转换时,这两个方法是公用的,用于调用容器子类。 如果他们被覆盖,覆盖应确保打电话给超级。
这两个方法中的父参数是零,当一个孩子被从其父母移除; 否则等于新的父视图控制器。
13. didReceiveMemoryWarning()
父应用程序收到内存警告时调用。 在iOS 6.0上,默认情况下将不再清除视图。
init(coder:)
在Storyboard中创build应用程序的视图时, init(coder:)
是被调用来实例化视图控制器并使其init(coder:)
的方法。 这个方法的契约实际上是在NSCoding协议中定义的,所以你不会在UIViewController
文档中看到它。
当这个方法被调用时,你的视图很可能会在不久的将来(或者不久的将来)显示出来,但是在这一点上并不能保证它真的被显示出来。 所以这可能是开始整理事物的好时机,但这里不要太多,否则会浪费处理能力。 在这个方法中,你可能实例化依赖关系,包括你将以编程方式添加到视图中的子视图。 注意init(coder:)
只在对象的生命期间被调用一次,因为所有的init方法都是。
viewDidLoad()
在视图加载到内存之后调用init(coder:)
之后,此方法在视图控制器对象的生命周期中也只调用一次。 这是一个很好的地方做任何视图初始化或设置你没有在故事板做。 也许你想以编程方式添加子视图或自动布局约束 – 如果是这样,这是做这两个任务的好地方。 请注意,只是因为视图已经加载到内存中并不一定意味着它将很快显示 – 为此,您将需要查看viewWillAppear
。 哦,记得在你的实现中调用super.viewDidLoad()
,以确保你的超类的viewDidLoad有机会做它的工作 – 我通常在实现开始时调用超级权利。
viewWillAppear(_:)
总是在viewDidLoad
之后调用(出于显而易见的原因,如果你仔细想一下),并且在视图出现在用户的屏幕上之前,调用viewWillAppear
。 这使您有机会做任何最后一分钟的视图设置,启动一个networking请求(当然在另一个class级),或者刷新屏幕。 与viewDidLoad
不同的是, viewWillAppear
在第一次显示视图时以及再次显示视图时调用,因此可以在视图控制器对象的生命期内多次调用viewWillAppear
。 当用户点击后退button,closures模式对话框,在选项卡栏控制器中select视图控制器的选项卡或其他各种原因时,视图即将出现。 确保在实现中的某个时刻调用super.viewWillAppear()
,我通常首先执行它。
viewWillDisappear(_:)
与viewWillAppear
类似,在视图从屏幕消失之前调用此方法。 和viewWillAppear
一样,这个方法在视图控制器对象的生命期间可以被多次调用。 当用户离开屏幕时,可能会调用它 – 可能会解散屏幕,select另一个选项卡,点击显示模式视图的button,或者沿着导航层级进一步导航。 这是隐藏键盘,保存状态,并可能取消运行定时器或networking请求的好地方。 与视图控制器生命周期中的其他方法一样,请确保在viewWillDisappear
中的某个点处调用super
。