title: Section headers "bounce" when UITableView is reloaded
body: <p>I have a <code>UITableView</code> which under goes a batch update when the state of app changes.  The change can effect a number of rows/sections or only one section (but 1 or more rows).</p>
  <p>I've noticed that when under going a single section update (which may effect a number of rows in the section), the section headers for the other sections &quot;bounce&quot; or are &quot;moved&quot; from their previous position and then animated back into place.</p>
  <p>A picture paints a thousand words...</p>
  <p><a href="https://i.stack.imgur.com/rLI7q.gif" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/rLI7q.gif" alt="Video Capture" /></a></p>
  <p>These sections are not part of the batch update.</p>
  <p>The <code>UITableView</code>/<code>Controller</code> is setup through a story board targeting iOS 11.  The <code>UITableView</code> is making use of the &quot;Estimated&quot; row and section heights and the cells are laid out using auto layout.</p>
  <p><a href="https://i.stack.imgur.com/ADCZd.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ADCZd.png" alt="Xcode storyboard properties" /></a></p>
  <p>The <code>UITableViewController</code> makes use of a larger data model which managers the state and state change operations. The API ensures that the required updates are calculated based on the required state of the model (i.e. deletes and updates relate to the &quot;previous&quot; state, inserts related to the &quot;new&quot; state)</p>
  <p>The last step is to apply the calculated changes to the table view through a batch update process...</p>
  <pre><code>tableView.beginUpdates()
  
  // Calculate the rows/sections which need to be changed
  
  if let ops = operation.sections[.delete], ops.count &gt; 0 {
      tableView.deleteSections(ops, with: deleteSectionAnimation)
  }
  if let ops = operation.sections[.update], ops.count &gt; 0 {
      tableView.reloadSections(ops, with: reloadSectionAnimation)
  }
  if let ops = operation.sections[.insert], ops.count &gt; 0 {
      tableView.insertSections(ops, with: insertSectionAnimation)
  }
  
  if let ops = operation.rows[.delete], ops.count &gt; 0 {
      tableView.deleteRows(at: ops, with: deleteRowAnimation)
  }
  if let ops = operation.rows[.update], ops.count &gt; 0 {
      tableView.reloadRows(at: ops, with: reloadRowAnimation)
  }
  if let ops = operation.rows[.insert], ops.count &gt; 0 {
      tableView.insertRows(at: ops, with: insertRowAnimation)
  }
  tableView.endUpdates()
  
  tableView.reloadData()
  tableView.layoutIfNeeded()
  </code></pre>
  <p>The row and section animation properties (i.e. <code>deleteSectionAnimation</code>) are set to <code>automatic</code>.  I've tried setting the section animations to <code>none</code> without any differences</p>
  <p>I've tried removing the <code>reloadData</code> and <code>layoutIfNeeded</code> in varying combinations and while they create other issues, they don't seem to come close to resolving this issue</p>
  <p>One thing I've noticed, is this only seems to occur when the updates occurring to the <code>UITableView</code> are been done off screen</p>
  <p>I've spend some time trying to find a solution to the issue (like not calling <code>reloadData</code>) but can't find something which works.</p>
  <p>Is there some other property, function I should look at or is the order in which the updates are been executed wrong?</p>
  <h1>Notes</h1>
  <ul>
  <li>This is a &quot;static&quot; table, setup through storyboards</li>
  <li>The rows and sections are been added/removed during state changes, which seems to trigger issues/changes in the scroll view</li>
  <li>While disabling animation (with <code>UIView.setAnimationsEnabled</code>) does seem to fix the issue, it's an undesirable solution, as it removes the animations for all updates (on or off screen)</li>
  <li>The issue only occurs when the scroll view is NOT at the top of the view, updates/animations occurring when the table view is scrolled all the way to the top have no issues</li>
  <li>I've tried using <code>indexPathsForVisibleRows</code> to determine if the updates are occurring on or off the screen, and disable the animation using <code>UIView.setAnimationsEnabled</code> but it doesn't solve the issue if the update occurs on the screen while the table view is not scrolled to the top of the scroll view</li>
  </ul>