tags:

views:

786

answers:

3

When and how is layoutIfNeeded used? I know that when we change the layout of a view, we can call setNeedsLayout to update the layout but not sure when layoutIfNeeded should be used.

NOTE: I have layoutIfNeeded used in actual code but forgot in what context it was used.

A: 

setNeedsLayout actually calls layoutIfNeeded, so if your calling setNeedsDisplay there's no reason to call layoutIfNeeded. In this way setNeedsLayout is a convenience method for calling layoutIfNeeded which does the heavy lifting.

ennuikiller
A: 

I was under the impression that you use layoutIfNeeded when you want to make sure layoutSubviews has been called since a setNeedsLayout, and otherwise do nothing if setNeedsLayout hasn't been called since the last layoutSubviews.

Except in practice I don't think layoutIfNeeded immediately calls layoutSubviews (but calls in the next run loop). I'm not entirely sure about this point though.

Gabe
+3  A: 

layoutIfNeeded forces the receiver to layout its subviews immediately if required.

Suppose you have overridden layoutSubviews, and UIKit feels that your view requires layout for whatever reason (e.g. you called setNeedsLayout when handling some user action). Then, your custom layoutSubviews method will be called immediately instead of when it would normally be called in the regular UIKit run loop event sequence (after event handling, but before drawRect:).

An example of why you might need to call layoutIfNeeded within a single run loop:

  1. You resize a custom view containing a table view with a custom layout. setNeedsLayout is set so that layoutSubviews will be called later.
  2. A controller object asks the table view to scroll to some particular cell when handling a user event.
  3. Your custom view performs some custom sizing of the table view in layoutSubviews that changes the table view size.

The problem is when the controller asked the table view to scroll (step 2), the table view had bounds that were stale. The updated bounds would only be set on the table view later (step 3). What the controller wanted the table view to scroll to may not actually be visible after layoutSubviews is done. A solution then would be for the controller to call layoutIfNeeded in situations where it knows this might occur.

Allen Ding