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.

优化你创建之任何视图所拥有的layoutSubviews方法是非常重要的,因其可能频繁呗调用,而且有带来循环调用的潜在威胁(在layoutSubviews中引用一个setNeddsLayout方法将会创建非常影响你apps性能的循环)。

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

Screen-shot-2011-03-16-at-11.28.52-AM.pn

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.

Share

6 Comments

  • 856a8958ce6a5d0ca3bc21a2f537d1f0?s=40&d=

    By Dan Wineman, March 29, 2011 @ 9:51 am

    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.

  • 48cf6c6dfa8b6aba8eeeb34136526fd1?s=40&d=

    By Robb Albright, September 21, 2011 @ 12:35 pm

    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.

  • 7dde8d5306a7242734b4e7fc7a2993b0?s=40&d=

    By Juguang XIAO, September 25, 2011 @ 10:22 pm

    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