Question 1
View bounds and layout timing
Where do common mistakes happen when reading view bounds or forcing layout too early?
Follow-ups
- When is
viewDidLoadthe wrong place to readview.bounds?
Answer outline
Bounds and layout mistakes cluster around three patterns:
- 1.Bounds read too early — in
viewDidLoad,view.boundsis often not final. The system hasn’t finished layout for the current orientation, safe area, or container size. Setting layer frames or clipping paths from those values gives wrong sizes until something forces a relayout. - 2.
layoutIfNeeded()as a band-aid — sprinkling it to silence ambiguous constraint warnings masks the real problem and can add extra layout passes. Fix the constraints. Calling it inviewDidLoadbefore the view hierarchy is in a window still yields stale geometry. - 3.One-time safe area reads —
safeAreaInsetscan change afterviewDidLoadwhen bars show or hide, on rotation, in split view, or inside a custom container. Don’t cache a single read at load time; useview.keyboardLayoutGuidefor keyboard avoidance on modern iOS.
Prefer Auto Layout constraints wherever possible — they stay correct across rotations, safe area changes, and container transitions without manual pixel work.
Principles
- Treat
viewDidLoadas wiring and subview creation — not the moment of truth for final frames. - Read geometry and position layers in
viewDidLayoutSubviews(aftersuper) when pixels are required. layoutIfNeeded()is a timing tool for animating constraint changes — not a fix for ambiguous layout.safeAreaInsetsare not stable at load time — respond to changes rather than reading once.
Geometry-dependent work — defer to viewDidLayoutSubviews
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// bounds now match container + safe area for this pass
gradientLayer.frame = view.bounds
}
The legitimate use is driving a constraint animation, not papering over missing constraints:
Correct use of layoutIfNeeded() — animate a constraint change
heightConstraint.constant = 200
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded() // animates the constraint change
}
Follow-up angles
- SwiftUI: avoid assuming one-shot size in
onAppear; useGeometryReader/onGeometryChangewhen layout depends on proposed size.