AutoLayout nature

AutoLayout is essentially a linear equation parsing engine — a layout engine.

Auto Layout is no longer concerned with constant view size and position. Instead, we focus on the relationship between views, describe the constraint relations of views to establish a set of linear equations of equality or inequality, and then determine the frame of the control by analyzing the equations.

An NSLayoutConstraint object is essentially a linear equation that represents the layout relationship between two views (only the view itself when representing dimensions). This equation can be a linear equation or a linear inequality.

Multiple constraint objects constitute a constraint set, which is essentially a linear system of equations representing the layout relationship between multiple views on an interface. Linear equations in a system of equations, ordered in numerical order of priority.

The principle of AutoLayout

Stick to a consistent layout

Apple’s advice is to choose a layout that works and be consistent.

Create sufficient, satisfiable constraints

The set of constraints must be sufficient and satisfiable. Insufficient constraints (insufficient constraints) and unsatisfied constraints (constraint conflicts) can cause view dislocation and view loss. Creating sufficient, satisfiable constraints requires following certain layout principles.

AutoLayout mechanism

The AutoLayout layout process involves a delay mechanism, so it is not necessary to redraw the layout as soon as there is a constraint update. When there is a constraint change, the default method of the system is to delay the update, in order to achieve batch change constraints, draw views, avoid frequent traversing view hierarchy, and optimize performance. When the update constraint is too slow to affect the sequential code logic, it can also force the update immediately.

  • layoutIfNeeded

Use this method to force the view to update the layout immediately. With automatic layout, the layout engine updates the position of the view as needed to accommodate changes in constraints. This method uses the view receiving the message as the root view and lays out the view subtree from the root. If there are no pending layout updates, this method exits without modifying the layout or calling any layout-related callbacks.

  • setNeedsLayout

This method logs the request and returns it immediately. Because this method does not force an immediate update but waits for the next update cycle, it can be used to invalidate the layout of multiple views before updating any view. This behavior allows you to consolidate all layout updates into one update cycle, which generally improves performance.

AutoLayout process

After App starts, RunLoop loops to check whether there are constraint changes in the layer tree.

When RunLoop detects a constraint change (directly or indirectly setting, updating, or removing the constraint); The layout engine recalculates the layout, and setNeedsLayout is called by the parent view whose position and size have changed due to constraint updates. The new frame of the view already exists in the layout engine, but the position and size of the view have not been updated.

Then we move into the deferred layout phase, which begins by traversing the view hierarchy from the child to the parent view, calling the updateConstraints method of UIView. Make sure that the view that will be changed is updated at this point (to be fault-tolerant before traversing the view tree and rearranging the view). The second step is to traverse the view hierarchy from the child to the parent, calling the lyoutSubviews method (UIViewController is viewWillLayoutSubviews) that is marked as the view that needs to be laid out when the update constraint is called, and asking the method caller to rearrange its child views. In fact, this step is to read the position and size values of the view from the layout engine, set them on the corresponding view, and draw them.

AutoLayout supplement

Two steps to constrain change:

  1. Constraint update;

Constraints, as inputs, are stored in the layout engine in the form of a set of linear equations. When the change of the constraint equations is involved, it is a constraint change. Such as activating/invalidating constraint objects; Modify constraint constant constant; Modify constraint priority (change the ordering relationship of constraint equations); Modify the structure of the view tree.

  1. The layout engine recalculates the layout.

Constraint expressions are made up of variables that represent the position and size of the view. When the constraint is updated, the layout engine recalculates the layout. After recalculating the layout, the parent view of the view whose position or size changed due to constraint updates calls the setNeedsLayout method to mark the layout. At this point, the view’s new frame already exists in the layout engine, but the view has not updated its position or size. The deferred layout will then be scheduled for execution.

Two steps to delay layout:

  1. Constraint updated

In the deferred layout phase, the constraints are updated again (traversing the view hierarchy from the child to the parent, calling the updateConstraints method of UIView). Make sure that the view that will be changed is updated at this point, before traversing the view tree and rearranging the view.

  1. Reassign the view frames to update the position and size of the view

Traversing the view hierarchy from child to parent, calling the lyoutSubviews method (UIViewController is viewWillLayoutSubviews) that is marked as the view that needs to be laid out when the update constraint is called, allowing the method caller to rearrange its child views. In fact, this step is to read the position and size values of the view from the layout engine, set them on the corresponding view, and draw them.

The frame view itself has a value before the layoutSubviews method is called, and the value remains unchanged after the layoutSubviews method is called. The subview frame is the old value until the method is called, and the new value is assigned after the method is called.