title: How to, simply, wait for any layout in iOS?
body: <p>Before beginning note that this has nothing to do with background processing. There is no &quot;calculation&quot; involved that one would background.</p>
  <p><strong>Only UIKit</strong>.</p>
  <pre><code>view.addItemsA()
  view.addItemsB()
  view.addItemsC()
  </code></pre>
  <p>Let's say on a 6s iPhone</p>
  <h1>EACH of these takes one second for UIKit to construct.</h1>
  <p>This will happen:</p>
  <p><a href="https://i.stack.imgur.com/wYXBV.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/wYXBV.gif" alt="one big step" /></a></p>
  <h1>THEY APPEAR ALL AT ONCE. To repeat, the screen simply hangs for 3 seconds while UIKit does a massive amount of work. Then they all appear at once.</h1>
  <p>But let's say I want this to happen:</p>
  <p><a href="https://i.stack.imgur.com/XgWQ9.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/XgWQ9.gif" alt="enter image description here" /></a></p>
  <h1>THEY APPEAR PROGRESSIVELY. The screen simply hangs for 1 second while UIKit builds one. It appears.  It hangs again while it builds the next one. It appears. And so on.</h1>
  <p>(Note &quot;one second&quot; is just a simple example for clarity. See the end of this post for a fuller example.)</p>
  <p>How do you do it in iOS?</p>
  <p>You can try the following. <em>It does not seem to work</em>.</p>
  <pre><code>view.addItemsA()
  
  view.setNeedsDisplay()
  view.layoutIfNeeded()
  
  view.addItemsB()
  </code></pre>
  <p>You can try this:</p>
  <pre><code> view.addItemsA()
   view.setNeedsDisplay()
   view.layoutIfNeeded()_b()
   delay(0.1) { self._b() }
  }
  
  func _b() {
   view.addItemsB()
   view.setNeedsDisplay()
   view.layoutIfNeeded()
   delay(0.1) { self._c() }...
  </code></pre>
  <ul>
  <li><p>Note that if the value is too small - <strong>this approach simply, and obviously, does nothing</strong>. UIKit will just keep working. (What else would it do?). If the value is too big, it's pointless.</p>
  </li>
  <li><p>Note that currently (iOS10), <em><strong>if I'm not mistaken</strong></em>: if you try this trick with the trick of a zero delay, it works erratically at best. (As you'd probably expect.)</p>
  </li>
  </ul>
  <h1>Trip the run loop...</h1>
  <pre><code>view.addItemsA()
  view.setNeedsDisplay()
  view.layoutIfNeeded()
  
  RunLoop.current.run(mode: .defaultRunLoopMode, before: Date())
  
  view.addItemsB()
  view.setNeedsDisplay()
  view.layoutIfNeeded()
  </code></pre>
  <p>Reasonable.  <strong>But our recent real life testing shows that this seems to NOT work in many cases.</strong></p>
  <p>(ie, Apple's UIKit is now sophisticated enough to smear UIKit work beyond that &quot;trick&quot;.)</p>
  <p>Thought: is there perhaps a way, in UIKit, to get a callback when it has, basically, drawn-up all the views you've stacked up?  Is there another solution?</p>
  <p>One solution seems to be .. put the subviews <em><strong>in controllers</strong></em>, so you get a &quot;didAppear&quot; callback, and track those.  <strong>That seems infantile</strong>, but maybe it's the only pattern?  Would it really work anyway? (Merely one issue: I don't see any guarantee that didAppear ensures all subviews have been drawn.)</p>
  <hr />
  <h1>In case this still isn't clear...</h1>
  <p>Example everyday use case:</p>
  <p>• Say there are perhaps <strong>seven of the sections</strong>.</p>
  <p>• Say each one typically takes <strong>0.01 to 0.20</strong> for UIKit to construct (depending on what info you're showing).</p>
  <p>• If you just <strong>&quot;let the whole thing go in one whack&quot;</strong> it will often be OK or acceptable (total time, say 0.05 to 0.15) ... but ...</p>
  <p>• there will often be a tedious pause for the user as the &quot;new screen appears&quot;.  (<strong>.1 to .5 or worse</strong>).</p>
  <p>• Whereas if you do what I am asking about, it will always smooth on to the screen, one chunk at a time, with the minimum possible time for each chunk.</p>