title: Creating an autolayout-based metrics view
body: <p>I have a reusable view I will be using in <code>UITableViewCell's</code> and <code>UICollectionViewCell</code>'s, and need to get its dimensions for <code>tableView:heightForRowAtIndexPath:</code>.  Some subviews have stuff going on inside <code>layoutSubviews</code> so I can't call <code>systemLayoutForContentSize:</code>, instead my plan is to:</p>
  
  <ol>
  <li>Instantiate the metrics view.</li>
  <li>Set the size to include the desired width.</li>
  <li>Populate it with data.</li>
  <li>Update constraints / Layout subviews.</li>
  <li>Grab the height of the view or an internal "sizing" view.</li>
  </ol>
  
  <p>The problem I'm running into is that I cannot force the view to layout without inserting it into the view and waiting for the runloop.</p>
  
  <p>I've distilled a rather boring example.  Here's View.xib.  The subview is misaligned to highlight that the view is never getting laid out even to the baseline position:</p>
  
  <p><img src="https://i.stack.imgur.com/mxBMA.png" alt="View.xib"></p>
  
  <p>On the main thread I call:</p>
  
  <pre><code>UIView *view = [[UINib nibWithNibName:@"View" bundle:nil] instantiateWithOwner:nil options:nil][0];
  
  NSLog(@"Subviews: %@", view.subviews);
  view.frame = CGRectMake(0, 0, 200, 200);
  
  [view updateConstraints];
  [view layoutSubviews];
  NSLog(@"Subviews: %@", view.subviews);
  
  [self.view addSubview:view];
  [view updateConstraints];
  [view layoutSubviews];
  NSLog(@"Subviews: %@", view.subviews);
  
  dispatch_async(dispatch_get_main_queue(), ^{
      NSLog(@"Subviews: %@", view.subviews);
  });
  </code></pre>
  
  <p>I get out the following view information:</p>
  
  <pre><code>1) "&lt;UIView: 0x8bad9e0; frame = (50 50; 220 468); autoresize = W+H; layer = &lt;CALayer: 0x8be0070&gt;&gt;"
  2) "&lt;UIView: 0x8bad9e0; frame = (50 50; 220 468); autoresize = W+H; layer = &lt;CALayer: 0x8be0070&gt;&gt;"
  3) "&lt;UIView: 0x8bad9e0; frame = (50 50; 220 468); autoresize = W+H; layer = &lt;CALayer: 0x8be0070&gt;&gt;"
  4) "&lt;UIView: 0x8bad9e0; frame = (0 100; 100 100); autoresize = W+H; layer = &lt;CALayer: 0x8be0070&gt;&gt;"
  </code></pre>
  
  <p>1 indicates that the fresh-out-of-the-NIB view hasn't been laid out. 2 indicates that <code>updateConstraints/layoutSubviews</code> did nothing. 3 indicates that adding it to the view hierarchy did nothing. 4 finally indicates that adding to the view hierarchy and one pass through the main-loop laid out the view.</p>
  
  <p>I would like to get to the point where I can get the view's dimensions without having to let the application handle it or perform manual calculations (string height + constraint1 + constraint2) on my own.</p>
  
  <p><strong>Update</strong></p>
  
  <p>I've observed that if I place <code>view</code> inside a <code>UIWindow</code> I get a slight improvement:</p>
  
  <pre><code>UIView *view = [[UINib nibWithNibName:@"View" bundle:nil] instantiateWithOwner:nil options:nil][0];
  UIWindow *window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
  view.frame = CGRectMake(0, 0, 200, 200);
  [window addSubview:view];
  [view layoutSubviews];
  </code></pre>
  
  <p>If <code>view.translatesAutoresizingMaskIntoConstraints == YES</code>, the view's immediate subviews will be laid out, but none of their children.</p>