title: What conditions can prevent layoutSubviews from being called after setNeedsLayout?
body: <h2>The problem</h2>
  
  <p>In a custom view of mine (a <code>UIScrollView</code> subclass) I am calling <code>setNeedsLayout</code> in response to a "reload data" event (triggered by an external source). Most of the time this works correctly and <code>layoutSubviews</code> is called when the next view layout cycle occurs. Sometimes, however, <code>layoutSubviews</code> is not called! Up until now I was living with the "certain knowledge" that <code>setNeedsLayout</code> <em>always</em> triggers <code>layoutSubviews</code>. Apparently I was wrong. I even tried calling <code>layoutIfNeeded</code> after <code>setNeedsLayout</code>, but still no success.</p>
  
  <h2>The question</h2>
  
  <p>Obviously, I would like to solve my particular problem. On the other hand, I would like to improve my understanding of the view layout process on iOS, so I am formulating my question in a general way: Do you know of any conditions that can prevent <code>layoutSubviews</code> from being called after <code>setNeedsLayout</code> has been called? Answers that focus on <code>UIScrollView</code> are quite welcome, since that is where I am having trouble.</p>
  
  <h2>Problem context</h2>
  
  <p>I am on iOS 7.1, using Xcode 5.1.1. Notes on the implementation of my custom scroll view:</p>
  
  <ul>
  <li>The scroll view has a single container view of type <code>UIView</code> that is always the same size as the scroll view content size</li>
  <li>The scroll view's <code>layoutSubviews</code> implementation places custom subviews into the container view by manually calculating the subviews' frames</li>
  <li>The custom subviews' implementation uses Auto Layout</li>
  </ul>
  
  <p>Here is how the <code>reloadData</code> implementation looks like:</p>
  
  <pre><code>- (void) reloadData
  {
    // Iterates through an internal array that holds the subviews,
    // then empties the array. Subviews are deallocated at this
    // point.
    [self removeAllSubviewsFromContainerview];
    self.contentOffset = CGPointMake(0, 0);
    // I verified that the content size is always greater than
    // CGSizeZero (both width and height)
    CGFloat contentWidth = [self calculateNewContentWidth];
    self.contentSize = CGSizeMake(contentWidth, self.frame.size.height);
    // Here is the problem: Sometimes this triggers layoutSubviews,
    // sometimes it does not.
    [self setNeedsLayout];
    // Adding the following line for debugging purposes does not
    // help, making it clear that setNeedsLayout has no effect.
    //   [self layoutIfNeeded];
  }
  </code></pre>
  
  <p>Last but not least, here are some observations I made:</p>
  
  <ul>
  <li><code>layoutSubviews</code> is called as expected if the content offset or content size change. <code>layoutSubviews</code> is <strong>not</strong> called in my particular case if these two values don't change. I first assumed that this observation is a general working principle of <code>UIScrollView</code>, i.e. that <code>layoutSubviews</code> is generally not called for <code>UIScrollView</code> unless content offset or content size change. However, when I wrote a couple of minimal projects I failed to reproduce this assumed "general" behaviour - in those projects <code>layoutSubviews</code> was always called as expected, regardless of whether content offset or content size changed or not.</li>
  <li><code>layoutSubviews</code> is always called as expected if the scroll view displays dummy <code>UILabel</code> instances instead of my own custom subviews</li>
  <li><code>layoutSubviews</code> is always called as expected if I use my own custom subviews, but replace Auto Layout in the custom subviews' implementation by manual frame calculations</li>
  </ul>
  
  <p>The last two observations have led me to believe that Auto Layout is somehow involved, but I really have no idea how this could affect how <code>setNeedsLayout</code> works.</p>