Home Articles

setNeedsLayout vs layoutIfNeeded vs layoutSubviews

A comprehensive guide on setNeedsLayout, layoutIfNeeded and layoutSubviews, let us see one easy implementation for the same in this article.

Demo of UIKit — setNeedsLayout vs layoutIfNeeded vs layoutSubviews

Demo of UIKit — setNeedsLayout vs layoutIfNeeded vs layoutSubviews

In the modern programming era, Developers have started building apps with the new Declarative Programming SwiftUI. However, UIKit still exists and supports the SwiftUI application.

Keith Harrison’s Modern Auto Layout was instrumental in providing me with a deep understanding of the layout engine.

Layout Pass or Layout Cycle

Layout Pass or Layout Cycle

Layout Cycle

Trigger

Changing the input to the layout engine. This can be achieved by adding or removing subviews, activating/deactivating constraints, Intrinsic Content Size, and Setting priorities and constants of a constraint.

Update Internal Model

The layout engine has an internal model of the size and position of each view and an equation that describes the relationship between those views. Changing/Triggering the input will cause the layout engine to update its internal model and that solves the equations for new values in terms of size (width, height) and origin/position of view (x-axis and y-axis).

Deferred Layout Pass

Now the internal model has changed. It has two layout passes over the view hierarchy.

  • The first pass will allow updating any constraints

  • The second pass calls layoutSubViews on each view allowing them to update the size and position of their subviews to match the internal model repositioning any views if needed.

                                                                  Override in ViewController and View

Override in ViewController and View

Updating Constraints

Call setNeedsUpdateConstraints to request an update constraints pass for a view but it is deferred.

Call updateConstraintsIfNeeded method to update the internal model immediately.

Repositioning Views

The default behaviour of layoutSubviews sets the bounds and center of each subview to new values from the layout internal model.

layoutSubViews

Lays out subviews.

func layoutSubviews()

layoutSubViews Reference

Subclasses can override this method as needed to perform a more precise layout of their subviews. We should override this method only if auto-resizing or constraint-based behaviors of the subviews do not offer the behaviour you want.

To request a layout pass for a view, call setNeedsLayout or layoutIfNeeded (immediately).

setNeedsLayout

Invalidates the current layout of the receiver and triggers a layout update during the next update cycle.

func setNeedsLayout()

setNeedsLayout Reference

Returns immediately without updating the layout. Instead, it marks the layout of the view changed and schedules a deferred layout pass to run on the application run loop. Calls layoutSubviews during the next update cycle.

layoutIfNeeded

Lays out the subviews immediately, if layout updates are pending.

func layoutIfNeeded()

layoutIfNeeded Reference

Calls layoutSubviews on the receiver if there are pending changes to force the layout engine to immediately update the size and position of subviews from the layout internal model. If no layout updates are pending, this method exits without modifying the layout or calling any layout-related callbacks.

Only call these methods on the main thread.

Call setNeedsLayout to manually schedule an update layout pass. Call layoutIfNeeded to force an immediate update on the view frames from the model.

layoutIfNeeded

layoutIfNeeded

setNeedsLayout

setNeedsLayout

Example Usage

import UIKit

widthConstraint.constant = 100.0

let animator = UIViewPropertyAnimator(duration: 1.0, curve: .easeInOut) {
    self.view?.layoutIfNeeded()
}
animator.startAnimation()

layoutIfNeeded Example

Points to Remember

  • layoutIfNeeded is a synchronous call that will let the system update the views and force the layout engine to redraw the views.

  • setNeedsLayout is a deferred call and asynchronous call that will mark the layout has changed but it will call layoutSubViews in the next cycle.

  • Both layoutIfNeeded and setNeedsLayout call layoutSubViews

  • Better to have setNeedsLayout before calling layoutIfNeeded for the safer side. But it is not required in all cases. Because layoutIfNeeded requires a signal to update.

  • For animations, using layoutIfNeeded is a better option than calling setNeedsLayout. It ensures any pending layout updates are applied before the animation, resulting in smoother performance.

  • The same logic applies to the setNeedsUpdateConstraints and updateConstraintsIfNeeded

Note

Please find the GitHub Repo

This is a free third party commenting service we are using for you, which needs you to sign in to post a comment, but the good bit is you can stay anonymous while commenting.