iOS布局周期

当我们开始构建iOS应用程序时,我们将面临与视图布局及其内容有关的几个问题。 通常,这些问题是在缺少有关视图实际更新时间的知识时发生的。 了解视图更新的方式和时间要求我们必须了解iOS应用程序的主运行循环 ,以及它与UIView提供的某些方法之间的关系。

iOS应用主运行循环

iOS应用程序的主运行循环处理所有用户输入事件,并触发应用程序中的相应响应。 与应用程序的任何用户交互都将添加到事件队列中

应用程序对象将事件从队列中移出并将它们分派到应用程序中的相应对象。 它实质上是通过解释来自用户的输入事件并为应用程序的核心对象中的输入调用相应的处理程序来执行运行循环。 这些处理程序调用由应用程序开发人员编写的代码。 这些方法调用返回后,控制权返回主运行循环, 更新周期开始。 更新周期负责布局和重绘视图。

UIViewController布局周期

ViewDidLoad()

该类已加载,但单个元素(子视图)不可操作,并且约束尚未完全解决。

调用此方法后,将创建视图控制器的视图,并确保所有插座均已就位。

此方法在视图控制器的生命周期中仅被调用一次,因此您可以将它用于只需要发生一次的事情。

ViewWillAppear ()

该视图将出现,但到目前为止尚未将其添加到视图层次结构中。 在视图出现之前立即调用,非常适合于隐藏/显示字段或您希望在视图可见之前每次进行的任何操作。 因为您可能会在视图之间来回移动,所以每次视图将出现在屏幕上时都会调用此方法。

ViewDidAppear()

该视图已添加到视图层次结构中。 解决了所有限制(您可以在屏幕上看到结果)。

ViewDidLayoutSubviews()

每当更新,旋转或更改视图或更改边界时,都会调用viewDidLayoutSubviews

需要注意的一点是,仅在对视图应用了所有自动 布局自动调整大小的计算之后,才调用此方法。 简而言之,每次视图大小更改并且重新计算视图布局时,都会调用viewDidLayoutSubviews

ViewWillDisappear()

viewWillAppear相似,此方法在视图从屏幕消失之前被调用。 与viewWillAppear一样,可以在视图控制器对象的生存期内多次调用此方法。 当用户离开屏幕导航时被调用。

ViewDidDisappear()

从屏幕中删除视图控制器后,将调用此方法。 通常,您可以重写此方法以停止视图控制器不在屏幕上时不应运行的任务。 例如,您可以停止收听通知,观察其他对象的属性或不再需要的网络呼叫。

Deinit()

像其他所有对象一样,在将视图控制器从内存中删除之前,它会被初始化。 通常,您可以重写deinit()来清除视图控制器已分配的资源,但这些资源不会被ARC释放。 您还可以停止以前的方法中未停止的任务,因为您希望将它们保留在后台。

注意 :如果视图控制器离开屏幕(在导航堆栈中按下),并不表示之后会释放它。 导航堆栈中所有以前的视图控制器都保留在内存中。

导航控制器仅在向上导航层次结构(弹出视图)时才释放视图控制器。 因此,您必须记住,不在屏幕上的视图控制器仍然可以正常工作并接收通知。

查看布局

UIView layoutSubviews方法处理视图及其所有子视图的重新定位和调整大小。 系统在需要重新计算视图框架时会调用此方法,因此,当您要设置框架并指定位置和大小时,应覆盖此方法。

layoutSubviews完成时,将在拥有该视图的视图控制器中触发对viewDidLayoutSubviews的调用。 由于layoutSubviews是在更新视图的布局后可以可靠地调用的唯一方法,因此应将任何依赖于布局和大小的逻辑放在viewDidLayoutSubviews而不是在viewDidLoadviewDidAppear 。 这是避免对其他计算使用陈旧的布局和定位变量的唯一方法。

很少有事件向系统发出信号,表明视图的布局已更改:

  • 它自己的边界 (不是框架)已更改。
  • 其直接子视图之一的范围已更改。
  • 子视图被添加到视图或从视图中删除