When is layoutSubviews called?
Building on the previous answer by @BadPirate, I experimented a bit further and came up with some clarifications/corrections. I found that layoutSubviews:
will be called on a view if and only if:
- Its own bounds (not frame) changed.
- The bounds of one of its direct subviews changed.
- A subview is added to the view or removed from the view.
Some relevant details:
- The bounds are considered changed only if the new value is different, including a different origin. Note specifically that is why
layoutSubviews:
is called whenever a UIScrollView scrolls, as it performs the scrolling by changing its bounds' origin. - Changing the frame will only change the bounds if the size has changed, as this is the only thing propagated to the bounds property.
- A change in bounds of a view that is not yet in a view hierarchy will result in a call to
layoutSubviews:
when the view is eventually added to a view hierarchy. - And just for completeness: these triggers do not directly call layoutSubviews, but rather call
setNeedsLayout
, which sets/raises a flag. Each iteration of the run loop, for all views in the view hierarchy, this flag is checked. For each view where the flag is found raised,layoutSubviews:
is called on it and the flag is reset. Views higher up the hierarchy will be checked/called first.
I had a similar question, but wasn't satisfied with the answer (or any I could find on the net), so I tried it in practice and here is what I got:
init
does not causelayoutSubviews
to be called (duh)addSubview:
causeslayoutSubviews
to be called on the view being added, the view it’s being added to (target view), and all the subviews of the target- view
setFrame
intelligently callslayoutSubviews
on the view having its frame set only if the size parameter of the frame is different - scrolling a UIScrollView
causes
layoutSubviews
to be called on the scrollView, and its superview - rotating a device only calls
layoutSubview
on the parent view (the responding viewControllers primary view) - Resizing a view will call
layoutSubviews
on its superview (Important: views with an intrinsic content size will re-size if the content that determines their size changes; for example, updating the text on a UILabel will cause the intrinsic content size to be updated and thus calllayoutSubviews
on its superview)
My results - http://blog.logichigh.com/2011/03/16/when-does-layoutsubviews-get-called/
https://developer.apple.com/library/prerelease/tvos/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/CreatingViews/CreatingViews.html#//apple_ref/doc/uid/TP40009503-CH5-SW1
Layout changes can occur whenever any of the following events happens in a view:
a. The size of a view’s bounds rectangle changes.
b. An interface orientation change occurs, which usually triggers a change in the root view’s bounds rectangle.
c. The set of Core Animation sublayers associated with the view’s layer changes and requires layout.
d. Your application forces layout to occur by calling thesetNeedsLayout
orlayoutIfNeeded
method of a view.
e. Your application forces layout by calling thesetNeedsLayout
method of the view’s underlying layer object.