UIView

UIView生命周期

本文系从外网翻译而来,在此附上原作者链接🔗
[view-lifecycle-ios]: https://candost.blog/view-lifecycle-in-ios/ “感谢”

ios中view的生命周期

  • 在学习啦application的生命周期后,view的生命周期对与iOS的开发者来说是另一个非常重要的事情
    每一个view都是用stroyboard,xibs,或者programmaatic创建的。从这些方法中脱离出来,真正理解view是什么时候被created,loaded,appeared或者destroyed能够帮助我们去更准确的理解我们所使用的方法 ,当我们去进行screen design,animations甚至business logic。

这些都有道理,但是我们为什么需要去知道这些呢

  • 当我们想到application lifecycle时,我们很容易的看到application进入background,suspended时什么正在发生。无论什么时候用户与app进行交互,只要发生对应的action,app的状态就会发生改变。然而,view的状态会须会在没有任何用户交互或者数据更改的情况下发生改变。
  • 一方面,当view的一个确定的状态发生改变时,我们或许需要去熟练的操作用户交互。例如,如果我们想要去使用custom view并且把它设置为UIViewController‘s view,我们必须去在 loadview 方法中实现它。或者如果我们的设计需要我们去监视landscape和portrait模式之间的不同,我们需要我们什么时候在代码中去做这种改变。因此理解全部的lifecycle 方法不仅会在代码中帮助我们,也会让我们变得更加有创造性和更好的使用user interface。

我们需要知道什么

  • 为啦更好的在恰当的时刻使用view,我们需要去知道view什么时候被created,loaded,appeared,changed,disappeared,和terminated。UIViewController的子类是负责管理这些view的。view controller有一个根view,这个view是UIView的实例。我们需要知道的是他们是如何一起发挥作用的。
    当UIView将要显示在屏幕上,展示给一些内容用户的时候,UIViewController处理着view后面的所有的逻辑。它告诉root UIView什么时候去出现在屏幕上。首先UIViewController创造他的root view 并且load它,在load它之后,它告诉屏幕去appear在屏幕上,然后在必要的时候disappear。

  • 此外,一个view controller或许会是另一个controller的孩子。所以,view controller的生命周期不仅与他的root view有关,也和其他的view controller有关系。

  • 最后,view controller的root view有他自己的内容和生命周期。root view有他的子视图比如说按钮,标签或者其他的UIview的子类。子视图的生命周期很多情况下没有被大多数开发者考虑,但是有些情况下是需要的,举个例子,当一个视图嵌入到另一个视图控制器时,我们去要去模仿这两个view的生命周期的动作,并在必要时调用合适的方法。

我们如何知道生命周期的事情

当一些事件发生的时候,UIViewController有很多方法来通知我们。例如,在加载过view之后我们能够重写viewDidload 方法去做一些合适的事情。或者重写loadView 方法用我们custom view来替换view controller的root view

  • 我们将会简单的看一下view controller和view的之间的关系去了解当前的状态。不要太关注每一个方法做什么,我们将会看一下对于每一个方法来说什么是重要的和什么时候去使用它。

UIView和UIViewController之间的关系

  • loadView:这个函数是view controller的root view被load的地方。view controller的view属性还是空的这个时候。如果我们想要创建一个custom view并把它设置为controller的root view的湖,那就需要重写这个方法。一旦我们重写了这个方法,我们必须去初始化custom view并且把它设置为view controller的view property,而且我们不能去调用他的父方法。因为他创造啦一个view并把这个view设置为他的root view。最后我们不需要直接调用这个方法(因为他是生命周期中的函数,会自动调用)

  • viewDidload:这个方式是在创建完view并且把它载入到内存中后调用的。但是view的bounds是没有确定的。我们一般重写这个方法去初始化view controller将会使用的object。如果我们重写这个方法,不要忘记去调用父方法(super)

  • viewWillAppear(_:)这个方法是在view即将出现在屏幕上时被调用。当这个方法被调用时view的bounds被确定但是方向还没有被确定,我们需要去关注一下这个当使用这个方法的时候。因为这个方法在每次view即将出现在屏幕上时都会被调用。类似的我们不要忘记去调用父方法

  • viewWillLayoutSubviews:在生命周期中,这是第一个可以去得到view的bounds的地方。这个方法是在layoutSubview被触发时立即被调用的。这个方法也会被在root view的subview被装载的时候调用。例如,他也会被在collection view的cells被装载时调用

  • viewDidLayoutSubviews:这个方法是在layoutSubviews被调用时立即调用的。subviews已经被设置啦大小,位置,约束和方向。同理,viewWillLayoutSubviews和viewDidLayoutSubviews也会被调用当屏幕的方向在纵向和横向之间切换时调用。所以关键点是当view的bounds更新时或者view的布局被计算过后这两个方法会被调用。我们也要调用super方法

  • viewDidAppear(_:)这个方法是在view可以被使用者看到的时候立即调用的。他是一个很好的位置去开始一个动画。和之前一样我们不要忘记去调用super方法

  • viewWillDisappear(_😃:当view将要从屏幕上消失时这个方法被调用。我们可以在这个地方做一些保存用户数据等事情。另一个可能是取消网络请求。我们能够重写这个方法如果我们想要去移交responder 工作到另一个视图中当这个视图消失时

  • viewDidDisappear(_😃:当view已经从屏幕上消失后调用这个方法。view在这个时候被从view hierarchy从移除

在这里插入图片描述

  • 我们看啦最普通的关系,view和view controller之间的关系是UIKit中最普通的。而且view controller不仅仅有和view的关系他还和其他的view controller有关系比如父子关系

UIViewController-UIViewcontroller Relationship

理解这个关系和view controller中的生命周期是相当重要的事情如果我们把一个view controller嵌入到另一个aview controller之中。或许我们需要手动的调用一些生命周期的方法去通知系统一些状态。下面是一个添加和移除child view controller的例子

在这里插入图片描述

我们来看一下关于lifecycle我们做了什么。在创建了view controller之后我们向parent添加child。这个叫做childViewController.WillMove对我们来说。所以我们不需要去手动的调用他们,接着我们需要去把child view controller的view添加到parent的view去让它们两个有联系。系统将会装载两个view并且会把一个view添加到另一个view里边通过调用addSubview。接下来我们通过调用didMove去通知系统然后系统将会处理展示view controller,调用view‘s controller’s 必须的方法等各种剩下的事情。比如viewDidload,viewDidAppear等

另一方面,当把child view controller从parent中移除时,我们必须调用WillMove去通知system child view controller将会被移除从parent中。接着,我们移除他的view和它本身从parent中。正如我们所见的,我们不需要去调用didMove当我们移除它的时候。removeFromParent方法自动替我们调用那些方法

此外,我们能够重写WillMove和didMove。如果我们需要去知道一个view controller被添加到一个view controller,我们能够重写这些方法实现自己自定义的操作。

父视图和子视图的关系很常见。它是非常重要的去理解两个view controller之间的生命周期以便于能够在一个确切的时机去调用一些必要的方法。如果我们忘记去调用一个方法,我们或许会导致app里一些内存问题。现在我们讲到最后一个点——view和它的subView之间的关系和生命周期。

View - View(SubViews)Realationship

在这个关系中,大多数lifecycle是被自动调用并不需要去调用这些方法像parent和child view controller的关系。
例如,即使我们尝试去调用WillRemoveSubview方法,他也没啥用。这个实现是空的。系统调用下面的方法仅仅是为了通知我们当一些事情被改变之后。这个地方并没有太多地方需要去讨论。了解我们在哪里有去检测subview什么时候被添加或者view被作为subview添加或者出现在窗口将会给我们一些机会去实现额外的动作在这些过程中。

这里是一些UIView的lifecycle方法

  • didAddSuview
  • willRemoveSubView
  • willMove
  • didMovewToSuperview
  • willMove
  • didMovewToWindow

在这里再强调一下关于removeFromSuperview。如果我们想要把一个视图从它的父视图移除的话,我们调用这个。调用这个方法将会移除所有的约束在视图和它的子视图中。我们不应该调用这个方法在视图的draw方法中。

Last Words

仅仅知道application,view controller,view lifecycle是不够的对于理解整个关系和开发一个好的iOS的application。掌握生命周期方法的使用是非常重要的对于在合适的地方进行合适的操作尤其是使用UIKit classes的自定义的子类的时候。现在我们知道了lifecycle,我们能够什么时候在屏幕后面什么正在进行和进行干预

一些执行顺序 (并非翻译,自己加的)

init->
willMoveToSuperview->
didMoveSuperview->
(如果有子view)->
subview的willMoveToSuperview->
subview的didMoveSuperview->
didAddSubview->
addSubview-viewWillAppear->
loadViewIfNeeded->
willMoveToWindow->
(如果有子view)->
subview的willMoveToWindow->
subview的didMoveToWindow->
didMoveToWindow->
viewWillLayoutSubviews->
layoutSubviews->
viewDidLayoutSubviews->

layoutSubviews调用时机

  1. init初始化不会触发layoutSubviews

    但是是用initWithFrame 进行初始化时,当rect的值不为CGRectZero时,也会触发

  2. addSubview会触发layoutSubviews

  3. 设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化

  4. 滚动一个UIScrollView会触发layoutSubviews

  5. 旋转Screen会触发父UIView上的layoutSubviews事件

  6. 改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件

欢迎讨论

  • 翻译仓促,第一次翻译文章,见谅
  • 想要原文电子版欢迎加Q:2604385913
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值