When does layoutSubviews get called?

It’s important to optimize any UIView layoutSubviews method you create, as it can be frequently called, and has the potential for creating recursion (triggering a setNeedsLayout from layoutSubviews can create a loop that will grossly affect your apps performance). Layout subviews is called once per run loop on any view that has had setNeedsLayout or setNeedsDisplayWithRect: called on it. So in addition to any time you manually call these methods, it can be useful to know when the UI framework calls setNeedsLayout/setNeedsDisplay as this will trigger layoutSubviews.

For this purpose, I will define a few view relationships:

  • View1 – UIView class, root view for examples
  • View1.1 – UIScrollView class, subview of View1
  • View1.1.1 – UIView class, subview of View1.1 (No autoresize mask)
  • View1.1.2 – UIView class, another subview of View1.1 (Autoresize mask – flexible width)

I then ran the following tests.  An X means the view was layed out

From this I surmise the following:

  • init does not cause layoutSubviews to be called (duh)
  • addSubview causes layoutSubviews 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 calls layoutSubviews on the view having it’s frame set only if the size parameter of the frame is different
  • scrolling a UIScrollView causes layoutSubviews to be called on the scrollView, and it’s superview
  • rotating a device only calls layoutSubview on the parent view (the responding viewControllers primary view)
  • removeFromSuperview – layoutSubviews is called on superview only (not show in table)

Hopefully this is helpful information for you as well.

10 thoughts on “When does layoutSubviews get called?”

  1. I find that resizing (not moving, only resizing) any subview causes the superview to get -layoutSubviews sent to it, which I found unexpected. From your table it doesn’t look like you tested that case.

  2. I’m finding the same thing as Dan: If you resize view 1.1, then view1 will get layoutsubviews called on it.

    Surprising when you are using layoutsubviews to handle complex arrangement of subviews for orientation changes, but also want to move the subviews in response to user action.

  3. For device rotation, as you stated:

    – rotating a device only calls layoutSubview on the parent view (the responding viewControllers primary view)

    This is partially true. This can be true only when your VC is in the VC hierarchy (root at window.rootViewController), well this is most common case. In iOS 5, if you create a VC, but it is not added into any another VC, then this VC would not get any noticed when device rotate, therefore its view would not get noticed too by calling layoutSubviews

  4. Also I’ve noticed that you can do calls addSubview and removeFromSuperview in layoutSubviews without loops.
    BUT addSubview (as mentioned above) and removeFromSuperview also triggers layoutSubviews!!!

Leave a Reply

Your email address will not be published. Required fields are marked *