title: UITableView cell collapse animation looks bad
body: <p>I'm having a problem making cell collapse animation look consistently smooth. </p>
  
  <p>Am image is worth a thousand words. Here's two GIFs of the same table view:</p>
  
  <p><a href="https://i.stack.imgur.com/UN8dr.gif" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/UN8dr.gif" alt="Great"></a>
  <a href="https://i.stack.imgur.com/Go6AB.gif" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Go6AB.gif" alt="Terrible"></a></p>
  
  <p>Collapsing works really well for cell "6", but not for "5". It looks like the entire UITableView content jumps up before performing the collapse animation.</p>
  
  <p>I'm <strong>not</strong> using <code>UITableViewAutomaticDimension</code> for UITableView's <code>rowHeight</code>. Instead I'm providing row height by <code>tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath)</code> method and expanding/collapsing the cell using table view's <code>beginUpdates</code>/<code>endUpdates</code>. As you can see I'm also scrolling to the expanded row using <code>tableView.scrollToRow(at: indexPath, at: .none, animated: true)</code> (but only when expanding, so it probably doesn't matter).</p>
  
  <p>Subclass of UITableViewController is embedded in an UINavigationController with large title and search bar (not visible here, because the content is scrolled down). The UINavigationController is embedded in UITabBarController.</p>
  
  <p>Here's the relevant expand/collapse part. When passing a nil <code>indexPath</code> parameter, the already expanded cell will collapse.</p>
  
  <pre><code>func expandRow(at indexPath: IndexPath?) {
      selectedIndexPath = indexPath
      tableView.beginUpdates()
      tableView.endUpdates()
  
      if let ip = indexPath {
          tableView.scrollToRow(at: ip, at: .none, animated: true)
      }
  }
  </code></pre>
  
  <p>This method calculates row height and is called by both <code>tableView(_:heightForRowAt:)</code> and <code>tableView(_:estimatedHeightForRowAt:)</code>:</p>
  
  <pre><code>private func heightForRow(at indexPath: IndexPath) -&gt; CGFloat {
      var height: CGFloat
      if selectedIndexPath == indexPath {
          // Add some height variety
          height = 300 + CGFloat((indexPath.row % 4) * 20)
      } else {
          height = 70
      }
      return height
  }
  </code></pre>
  
  <p>Here's the GitHub repo: <a href="https://github.com/AleksanderMaj/CellCollapse" rel="nofollow noreferrer">https://github.com/AleksanderMaj/CellCollapse</a></p>
  
  <p>Any idea how to improve this?</p>
  
  <p>This problem is dimension-sensitive (this issue might not be reproducible following the same steps on a device with a different screen size). This was recorded on an iPhone 7 simulator with iOS 11.3.</p>
  
  <hr>
  
  <p>EDIT 1:
  It's important to preserve the automatic scrolling to the expanded cell.</p>