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.
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.
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.
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).
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.
Call setNeedsUpdateConstraints
to request an update constraints pass for a view but it is deferred.
Call updateConstraintsIfNeeded
method to update the internal model immediately.
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()
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()
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()
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.
import UIKit
widthConstraint.constant = 100.0
let animator = UIViewPropertyAnimator(duration: 1.0, curve: .easeInOut) {
self.view?.layoutIfNeeded()
}
animator.startAnimation()
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.