ios 视图生命周期_iOS视图绘图周期揭秘

ios 视图生命周期

Difficulty: Beginner | Easy | Normal | Challenging

难度:初学者| 容易 | 普通| 具有挑战性的

先决条件 (Prerequisites)

  • Some understanding of OO would be beneficial.

    对OO有一些了解将是有益的。

iOS应用程序的主运行循环 (Main Run Loop of an iOS App)

Apple has enabled the iOS SDK to handle user events and trigger responses within the application through use of the event queue.

Apple已启用iOS SDK,以通过使用事件队列来处理用户事件并在应用程序内触发响应。

When a user interacts with an application, the event is added to the event queue, which can then be handled by the application and potentially dispatched to other objects in the application. Once the events are handled, they then return control to the main run loop and begin the update cycle, which is responsible for laying out and drawing views.

当用户与应用程序进行交互时,该事件将添加到事件队列中,然后可由应用程序进行处理,并有可能分派给应用程序中的其他对象。 处理完事件后,它们会将控制权返回到主运行循环并开始更新周期,该更新周期负责布局和绘制视图。

更新周期 (The Update Cycle)

Once control is returned to the main run loop, the system renders layout according to constraints on view instances.

一旦控制权返回到主运行循环,系统就会根据视图实例的约束来呈现布局。

When a view is marked as requiring a change in the next update cycle, the system executes all the changes.

当视图标记为在下一个更新周期中需要更改时,系统将执行所有更改。

The system works through the run loop, then constraints before the deferred layout pass.

系统在运行循环中工作,然后在延迟的布局通过之前进行约束。

延期布局通行证 (Deferred layout pass)

Constraints would usually be created during the creation of the view controller (perhaps in the viewDidLoad() function).

通常在创建视图控制器的过程中会创建约束(也许在viewDidLoad()函数中)。

However, during runtime, dynamic changes to constraints are not immediately acted on by the system. Unfortunately, the change would be left in a stale state, waiting for the next deferred layout pass and — actually, that might never happen. The user is looking at an out-of-date view. Awful.

但是,在运行时,系统不会立即对约束进行动态更改。 不幸的是,更改将保持旧状态,等待下一次推迟的布局传递,并且-实际上,这可能永远不会发生。 用户正在查看过时的视图。 可怕。

Equally, other changes to objects (like changing a control’s properties) can also change the constraints on other objects, potentially leading to the same problem.

同样,对对象的其他更改(如更改控件的属性)也可以更改对其他对象的约束,从而可能导致相同的问题。

The solution to this is to request a deferred layout pass by calling setNeedsLayout() on the relevant view (or setNeedsUpdateConstraints()).

解决方案是通过在相关视图(或setNeedsUpdateConstraints() )上调用setNeedsLayout()来请求延迟的布局传递。

Technically, the deferred layout pass (according to the documentation) involves two passes:

从技术上讲,延迟的布局过程( 根据文档 )涉及两个过程:

  1. The update pass updates the constraints, as necessary. This calls updateViewConstraints method on all view controllers and updateConstraints method on all views.

    更新过程根据需要更新约束。 这将在所有视图控制器上调用updateViewConstraints方法,并在所有视图上调用updateConstraints方法。

  2. The layout pass repositions the view’s frames, as necessary. This calls viewWillLayoutSubviews on all view controllers and layoutSubviews on each view.

    布局过程根据需要重新定位视图的框架。 这将在所有视图控制器上调用viewWillLayoutSubviews ,并在每个视图上调用layoutSubviews

The relevant methods? They are right below but explored in depth further on in the article.

相关方法? 它们在下面,但在本文中将进一步深入探讨。

Image for post

无限循环的风险 (The Risk of Infinite Loops)

We are placing views onto a list to request an update on a deferred layout pass. The risk of doing so is that through every pass, another request for a deferred layout pass is made.

我们将视图放置在列表上,以请求对延迟的布局传递进行更新。 这样做的风险是,每经过一遍,就会提出另一个要求推迟布局的请求。

  • Always call the superclass when overriding a method.

    重写方法时,请始终调用超类。
  • Do not call setNeedsLayout() inside layoutSubviews.

    不要在layoutSubviews内部调用setNeedsLayout()

  • Do not call setNeedsUpdateConstraints() inside updateConstraints().

    不要在updateConstraints()内部调用setNeedsUpdateConstraints() updateConstraints()

使用setNeedsDisplay强制重画 (Force a Redraw With setNeedsDisplay)

setNeedsDisplay() forces a redraw of a particular view. Because you should never call draw(_ rect: CGRect) directly, you can think of setNeedsDisplay() as a method of asking UIKit for a redraw. Another way of thinking of this is that calling setNeedsDisplay() marks a view as dirty; that is, on the next update cycle, the view will be redrawn through a deferred layout pass.

setNeedsDisplay()强制重绘特定视图。 因为您永远不要draw(_ rect: CGRect)调用draw(_ rect: CGRect) ,所以可以将setNeedsDisplay()视为要求UIKit重绘的方法。 另一种思考方式是调用setNeedsDisplay()将视图标记为脏视图。 也就是说,在下一个更新周期,将通过推迟的布局遍历来重绘视图。

Since the pass is deferred, it will occur during the next update cycle, during which func draw(_:) will be called on all such views.

由于传递被推迟,因此它将在下一个更新周期内发生,在此期间,将在所有此类视图上调用func draw( _ :)

This seems a little bewildering to the beginner since most UI components take care of this for us. However, there can be a property that is not directly tied to a UI component, and we need to inform Swift of what’s what with our call.

对于初学者来说,这似乎有些令人困惑,因为大多数UI组件都会为我们解决这个问题。 但是,可能存在一个不直接绑定到UI组件的属性,我们需要将调用的结果告知Swift。

Image for post
Click for Gist 单击要点

使用setNeedsLayout触发布局刷新 (Trigger Layout Refreshes with setNeedsLayout)

When a view changes, the layout changes, and this requires a recalculation by Auto Layout.

视图更改时,布局也会更改,这需要通过“自动布局”进行重新计算。

Usually, the layout is automatically updated. That is, when a view is resized, it’s added to the view hierarchy, constraints are updated, and the device is rotated or the user scrolls.

通常,布局会自动更新。 也就是说,调整视图大小时,将其添加到视图层次结构中,更新约束,并旋转设备或滚动用户。

There are situations where we need to force the layout of a particular view instance to be recalculated. and these are covered by the next couple of methods.

在某些情况下,我们需要强制重新计算特定视图实例的布局。 这些将在接下来的两种方法中介绍。

setNeedsLayout() (setNeedsLayout())

setNeedsLayout() asks for a layout update on a particular view. This will take place on the next update cycle, which, due to the quick refresh of iOS device screens, should be fast enough that the user does not experience any lag.

setNeedsLayout()要求在特定视图上更新布局。 这将在下一个更新周期进行,由于iOS设备屏幕的快速刷新,更新周期应足够快,以使用户不会遇到任何延迟。

layoutIfNeeded() (layoutIfNeeded())

This is similar to layoutIfNeeded() in that it forces an immediate update of the layout. One particular instance where this is used is for the animation of constraints, which, due to animation, would need to be updated immediately.

这与layoutIfNeeded()类似,因为它强制立即更新布局。 使用该约束的一个特定实例用于约束动画 ,由于动画的原因,该约束需要立即更新。

layoutSubview (layoutSubview)

The layoutSubview method is called when the view resizes, including the very first time it is set. This means that overriding this would be a suitable place to set corner radius of a UIView, or similar.

当调整视图大小时,包括第一次设置视图时,都会调用layoutSubview方法。 这意味着覆盖此位置将是设置UIView或类似角度的半径的合适位置。

Rather than being called directly, this is triggered by the system when the view is first laid out (that is, on the first draw) as well as on rotation. It can be requested with setNeedsLayout() for the next drawing update or forced immediately through layoutIfNeeded().

当视图第一次被布局时(即在第一次绘制时)以及在旋转时,它由系统触发,而不是直接调用。 可以使用setNeedsLayout()请求进行下一次图形更新,也可以立即通过layoutIfNeeded()强制。

If you are working in a view controller viewDidLayoutSubviews(), is your similar method here.

如果您在视图控制器中工作,则viewDidLayoutSubviews()是此处的类似方法。

更新约束 (Update Constraints)

When views are updated, the func draw(_ rect: CGRect) method is called (if there is one).

更新视图时,将func draw( _ rect: CGRect)方法(如果有的话)。

Don’t use updateConstraints() for the initial setup of your view. Use it for best performance when you need to add, modify, or delete lots of constraints within a single layout pass. But in practice, it usually makes sense to change them in place in any case. So there may be performance reasons for using this method, but in general, you should not.

请勿在视图的初始设置中使用updateConstraints() 。 当您需要在单个布局遍中添加,修改或删除许多约束时,请使用它以获得最佳性能。 但实际上,在任何情况下都将它们更改到位通常是有意义的。 因此使用此方法可能会有性能方面的原因,但通常不应该这样做。

UpdateConstraints also has a sibling function for a viewController, updateViewConstraints(), which can be useful.

UpdateConstraints还具有viewController的同级函数updateViewConstraints() ,这可能会很有用。

了解坐标 (Understanding Coordinates)

Understanding how a view updates and how it relates to the methods in UIView are essential to your journey as a developer focusing on Swift.

作为专注于Swift的开发人员,了解视图如何更新以及如何与UIView中的方法相关是必不可少的。

The coordinates for any particular UIView start in the top-left hand corner, as the following diagram shows:

特定UIView的坐标从左上角开始,如下图所示:

Image for post
The 0,0 coordinate
0,0坐标

结论 (Conclusion)

Within UIKit, using views is extremely important. There is quite a lot to understand and get used to, but it’s important to come to grips with the concepts to help you on your journey as a developer.

在UIKit中,使用视图非常重要。 有很多要理解和习惯的东西,但是重要的是要掌握这些概念,以帮助您成为开发人员。

扩展您的知识 (Extend Your Knowledge)

翻译自: https://medium.com/better-programming/demystifying-the-view-drawing-cycle-fb1f7ac519f1

ios 视图生命周期

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值