Understanding setNeedsLayout, updateConstraints, and layoutSubviews in iOS
When building dynamic interfaces in UIKit, you often need to trigger layout updates or adjust subviews when the view’s size or state…
Understanding setNeedsLayout, updateConstraints, and layoutSubviews in iOS
When building dynamic interfaces in UIKit, you often need to trigger layout updates or adjust subviews when the view’s size or state changes. Three important methods appear frequently in this workflow:
**setNeedsLayout()****updateConstraints()****layoutSubviews()**
Although they belong to the same layout system, each method plays a distinct role at a different stage of the UIKit layout cycle. Understanding what each method does, when it is called, and how they interact is essential for writing reliable UI code.
This article explains each method clearly and in order.
UIKit’s Layout Cycle Overview
Whenever something changes in your interface — like constraints, view sizes, or device orientation — UIKit performs a layout pass.
This layout pass consists of three major phases:
- Constraint Update Phase
UIKit updates Auto Layout constraints.
Method involved:
updateConstraints() - Layout Phase
UIKit calculates and assigns frames to subviews.
Method involved:
layoutSubviews() - Drawing Phase
UIKit renders the view hierarchy on the screen.
Method involved:
draw(_:)
The three methods you use (setNeedsLayout, updateConstraints, layoutSubviews) participate in the first two phases only.
1. updateConstraints()
Purpose
updateConstraints() is responsible for installing or updating Auto Layout constraints.
This is the earliest method in the layout sequence that UIKit calls when constraints need to be updated. You override it when constraints change based on dynamic state.
When UIKit Calls It
UIKit calls updateConstraints() when:
- Constraints have changed
- You call
setNeedsUpdateConstraints() - A system-triggered layout pass occurs (rotation, text size change)
- Subviews are added or removed
- A constraint’s constant changes
Important: This method is not called on every layout pass — only when constraints have become invalid.
What You Do Inside It
You override it to activate, deactivate, or modify constraints.
Example:
override func updateConstraints() {
if isExpanded {
expandedConstraints.forEach { $0.isActive = true }
collapsedConstraints.forEach { $0.isActive = false }
} else {
collapsedConstraints.forEach { $0.isActive = true }
expandedConstraints.forEach { $0.isActive = false }
}
super.updateConstraints()
}
What You Should NOT Do
- Do not change frames
- Do not perform animations
- Do not add subviews
updateConstraints() is strictly for constraint changes.
2. setNeedsLayout()
Purpose
setNeedsLayout() tells UIKit:
“This view’s layout may be outdated. Please schedule a layout update.”
It does not perform layout immediately. It only marks the view as needing layout, and UIKit will handle it on the next run loop.
When You Call It
You call setNeedsLayout() when something changes that affects how subviews should be arranged. Examples:
- A property changes that affects layout
- A label gets new text
- Internal state changes (expanded/collapsed)
- You update the UI and want subviews to reposition
setNeedsLayout()
If you want layout immediately, you use:
layoutIfNeeded()
When UIKit Calls It Automatically
UIKit automatically triggers setNeedsLayout() when:
- Constraints change
- View frame or bounds change
- Adding/removing subviews
- Device orientation changes
- Intrinsic content size changes
3. layoutSubviews()
Purpose
layoutSubviews() is where UIKit performs the actual layout of the view.
This is the primary method you override when writing custom layout code.
Inside it, you position and size your view’s subviews based on:
- Resolved Auto Layout constraints
intrinsicContentSize- Manual frame calculations
When UIKit Calls It
UIKit invokes layoutSubviews() when:
- A layout pass occurs
- After constraints are updated
- The view’s bounds change
setNeedsLayout()was calledlayoutIfNeeded()forces immediate layout- Device orientation changes
- A subview is added or removed
What You Do Inside It
You update frames, adjust sizes, or make layout-related calculations.
Example:
override func layoutSubviews() {
super.layoutSubviews()
titleLabel.frame = CGRect(
x: 20,
y: 20,
width: bounds.width - 40,
height: 30
)
}
If Auto Layout is used, you typically only perform final adjustments here.
How They Work Together
Here is the exact order of events during a layout update:
- Something changes that affects layout
You or the system triggers
setNeedsLayout(). - UIKit schedules a layout pass It does not run immediately unless forced.
- UIKit checks constraints
Calls
updateConstraints()if needed (Only if constraints are invalid or updated.) - Constraints are resolved internally Sizes and positions are calculated.
- UIKit applies layout
Calls
layoutSubviews(). - Views are drawn
Calls
draw(_:).
This flow ensures constraints and layout remain synchronized.
Comparison Table
MethodPhaseCalled ByWhat It DoesDeveloper UseupdateConstraints()Constraint Update PhaseUIKitUpdates Auto Layout constraintsModify or toggle constraintssetNeedsLayout()Pre-layout triggerDeveloper / UIKitSchedules a layout passNotify that layout must updatelayoutSubviews()Layout PhaseUIKitApplies frames to subviewsCustom frame layout or final adjustments
Practical Example
Here’s a custom view that updates constraints when expanded and triggers layout updates properly.
class CustomView: UIView {
private let box = UIView()
var isExpanded = false
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(box)
box.backgroundColor = .red
}
required init?(coder: NSCoder) { fatalError() }
override func updateConstraints() {
if isExpanded {
heightConstraint.constant = 200
} else {
heightConstraint.constant = 80
}
super.updateConstraints()
}
override func layoutSubviews() {
super.layoutSubviews()
box.frame = bounds.insetBy(dx: 10, dy: 10)
}
func toggle() {
isExpanded.toggle()
setNeedsUpdateConstraints() // Constraints must recalc
setNeedsLayout() // Layout must rerun
}
}
Final Thoughts
These three methods serve different purposes within UIKit’s layout pipeline:
updateConstraints()updates the ruleslayoutSubviews()applies the layoutsetNeedsLayout()triggers the rerun of layout
Because each one participates at a different point in the layout cycle, using them correctly prevents layout glitches, unnecessary work, and inconsistent UI behavior.
메타데이터
- post_id
- bdd3eda042ca
- slug
- understanding-setneedslayout-updateconstraints-and-layoutsubviews-in-ios-bdd3eda042ca
- url
- https://medium.com/@bharathibala21/understanding-setneedslayout-updateconstraints-and-layoutsubviews-in-ios-bdd3eda042ca
- canonical_url
- https://medium.com/@bharathibala21/understanding-setneedslayout-updateconstraints-and-layoutsubviews-in-ios-bdd3eda042ca
- author_url
- https://medium.com/@bharathibala21
- status
- ok
- fetched_at
- 2026-08-08 16:47:33