希望了解iOS UIViewController的生命周期

Lor*_*o B 280 lifecycle uiviewcontroller xamarin.ios ios

你能解释一下管理UIViewController生命周期的正确方法吗?

我特别想知道如何使用Initialize,ViewDidLoad,ViewWillAppear,ViewDidAppear,ViewWillDisappear,ViewDidDisappear,ViewDidUnloadDispose在单触摸的方法UIViewController类.

Hai*_*der 399

UIViewController生命周期如下图所示:

http://rdkw.wordpress.com/2013/02/24/ios-uiviewcontroller-lifecycle/

一个视图控制器的生命周期,图解

  • viewWillLayoutSubviews和viewDidLayoutSubviews在此流程图中的位置如何? (15认同)
  • 该图表不准确.自iOS6以来,不推荐使用viewDidUnload:http://stackoverflow.com/questions/12509102/viewdidunload-no-longer-called-in-ios6 (7认同)
  • 这确实是根本**错误**。随着时间的流逝,另一个关于SO的完全错误答案的例子。计算是高度非静态的。 (2认同)

小智 397

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

有一个关于苹果公司的网站上丰富的文档在这里.尽管如此:

  • ViewDidLoad - 在创建类并从xib加载时调用.非常适合初始设置和一次性工作.

  • ViewWillAppear - 在视图出现之前调用,适用于隐藏/显示字段或每次在视图可见之前发生的任何操作.因为您可能在视图之间来回切换,所以每次您的视图即将出现在屏幕上时都会调用此视图.

  • ViewDidAppear - 在视图出现后调用 - 开始动画或从API加载外部数据的好地方.

  • ViewWillDisappear/ DidDisappear-相同的思路ViewWillAppear/ ViewDidAppear.

  • ViewDidUnload/ ViewDidDispose- 在Objective C中,这是你清理和释放东西的地方,但这是自动处理的,所以你真的不需要在这里做.

  • 该文本略有误导,因为ViewDidLoad不应该用于一次性工作.如果由于内存不足而卸载视图然后再次加载,则可能会多次调用它. (82认同)
  • 创建/初始化视图控制器时,实际上并未调用ViewDidLoad.它是在您第一次执行与视图控制器视图相关的任何视图时调用的.就像添加它作为子视图一样,设置框架等.当然,从笔尖加载时也会调​​用它. (4认同)
  • ViewDidAppear - 在视图出现后调用 - 开始动画或从API加载外部数据的好地方.为什么它是开始加载数据的好地方?为什么不viewDidLoad? (3认同)
  • 文档中哪里隐藏了"viewDidDispose"事件? (2认同)

onC*_*ion 160

这适用于最新的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> = 9.0中可用.因此,如果您支持iOS <9.0,那么不要指望它会出现在图片中.

加载视图控制器的视图(如果尚未设置).

3. viewDidLoad

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

加载视图后调用.对于在代码中创建的视图控制器,这是在-loadView之后.对于从nib取消归档的视图控制器,这是在设置视图之后.

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.

视图被取消,覆盖或以其他方式隐藏时调用.

9. viewDidDisappear

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

在视图被解雇,覆盖或以其他方式隐藏之后调用.默认不做任何事

现在,按照Apple的实现方法,您应该记得调用super该特定方法的实现.

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

希望这有帮助.谢谢.

更新 - 由于@ThomasW指向内部注释,viewWillLayoutSubviews并且viewDidLayoutSubviews在加载主视图的子视图时也会在其他时间调用,例如,当加载表视图或集合视图的单元格时.

  • 当加载主视图的子视图时,例如当加载表视图或集合视图的单元时,也会在其他时间调用`viewWillLayoutSubviews`和`viewDidLayoutSubviews`. (6认同)

Raj*_*n S 43

iOS 10,11 (Swift 3.1,Swift 4.0)

UIViewControllerUIKit开发商,

1. loadView()

这是子类在不使用nib时应创建自定义视图层次结构的位置.永远不应该直接打电话.

2. loadViewIfNeeded()

加载视图控制器的视图(如果尚未设置).

3. viewDidLoad()

加载视图后调用.对于在代码中创建的视图控制器,这是在-loadView之后.对于从nib取消归档的视图控制器,这是在设置视图之后.

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父:UIViewController?)

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

从子父中删除子项时,这两种方法中的父参数都是nil; 否则它等于新的父视图控制器.

13. didReceiveMemoryWarning()

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

  • 它真的很sux stackoverflow不会从整个线程中清除所有错误和不完整的答案.就方法调用而言,你的答案似乎已经完成了,所以我将假设你的答案是正确的并且可以使用它. (2认同)
  • @LogicsaurusRex 我同意。就像 SO 将问题标记为重复或受保护的方式一样,我认为它应该能够将答案标记为 *过时* 或 *过时* (2认同)

Saa*_*aad 28

截至iOS 6及以后版本.新图如下:

在此输入图像描述


gjg*_*jgj 19

这些方法viewWillLayoutSubviewsviewDidLayoutSubviews没有在图中提及,但这些方法在viewWillAppear和之间调用viewDidAppear.它们可以被多次调用.


Ale*_*ekh 19

让我们专注于负责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的生命周期图

有关更多信息,请查看UIViewController类参考.


Mat*_*ker 16

Haider的答案对于iOS 6之前是正确的.但是,从iOS 6开始,viewDidUnload和viewWillUnload永远不会被调用.该文档的状态:"视图不再低内存情况下清除,因此该方法不会被调用."


bob*_*ics 16

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

  1. loadView[一个]
  2. viewDidLoad[一个]
  3. viewWillAppear
  4. viewWillLayoutSubviews 是第一次完成边界
  5. viewDidLayoutSubviews
  6. viewDidAppear
  7. * viewWillLayoutSubviews并[b]
  8. * viewDidLayoutSubviews并[b]

脚注:

(一) -如果你手动零出在你的看法didReceiveMemoryWarning,loadViewviewDidLoad会被再次调用.也就是说,默认情况下loadView,viewDidLoad每个视图控制器实例仅调用一次.

(b)可以被称为额外的0次或更多次.