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. But still, the UIKit exists and supports in SwiftUI application.
Keith Harrison's Modern Auto Layout was instrumental in providing me with a deep understanding of the layout engine.
The layout cycle is as follows:
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 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.
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 behavior 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 behavior 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.
Call setNeedsLayout to manually schedule an update layout pass. Call layoutIfNeeded to force an immediate update to the view frames from the model.
layoutIfNeeded
setNeedsLayout
Example Usage
import UIKit
widthConstraint.constant = 100.0
let animator = UIViewPropertyAnimator(duration: 1.0, curve: .easeInOut) {
self.view?.layoutIfNeeded()
}
animator.startAnimation()
Points to Remember
The entire project can be found here
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.