23

video of the tableview animation bug

I have a table view which expands/collapse its cells.

As of iOS 11, the tableView starts to behave strangely on insertion and deletion of rows. The contentSize has changed before the animation block happens and consequently, in the video, you can see a buggy scroll back happening on collapsing cells. The animation just looks wrong.

This code worked perfectly on iOS 10. Do anyone know what has changed on Apple's side? Is this a known issue?

public func insertingRowsForAccordion(_ indexArray: [IndexPath], selectedRowIndex: Int) {
    beginUpdates()
    insertRows(at: indexArray, with: UITableViewRowAnimation.fade)
    endUpdates()

 // Scroll to selection after expanding children
    scrollToRow(at: IndexPath(row: selectedRowIndex, section: 0), at: UITableViewScrollPosition.top, animated: true)
}

public func removeRowsForAccordion(_ indexArray: [IndexPath]) {
    beginUpdates()
    deleteRows(at: indexArray, with: UITableViewRowAnimation.fade)
    endUpdates()
}
l.vasilev
  • 926
  • 2
  • 10
  • 23

5 Answers5

35

I have been having countless problems with iOS 11 UITableView. Going to every UITableView in my entire app and doing the following fixed all of my problems.

Set estimatedRowHeight, estimatedSectionHeaderHeight, and estimatedSectionFooterHeight to 0.

Source: iOS 11 Floating TableView Header

jvdev7
  • 776
  • 6
  • 6
  • This fixed a terrible bug I'd been trying to fix where moving around cells during a drag-to-reorder action would result in a failed glitchy, jerky animation. – Saoud Rizwan Sep 24 '17 at 04:14
  • This also fixed another bug where adding a new table view to a view controller would result in it gaining extra content inset at the top for no reason. – Saoud Rizwan Sep 24 '17 at 06:02
  • 1
    This fixed an iOS 11 bug for me where tableview would scroll back on each loadmore. Thanks. – asanli Oct 03 '17 at 13:38
  • Setting estimatedRowHeight to 0 alone fixed a weird bug for me in iOS11 (and only iOS11) where reloading rows towards the bottom of the table view (and above outside the screen at the same time) would result in cells flying up and down before finally arriving at their place. – nontomatic Oct 08 '17 at 14:20
  • @nontomatic I have the same issue, cells flying all over each other up and down – trapper Oct 10 '17 at 05:38
  • @trapper did the solution here fix it for you? The iOS 11 search controller is a pain. I have to implement all kinds of weird solutions that magically fix one thing, but cause another issue. Latest one is after dismissing the search controller the tableview will not anymore snap to the top of the first cell when scrolling. That can be fixed by setting the navigation bar to being translucent when in the willPresentSearchController (why would that solve the issue??), but then the navigation bar color will appear differently... bummer – nontomatic Oct 10 '17 at 07:46
  • 12
    Nope the solution here didn't help, it's horribly broken and looks terrible. I am using resizing cells with auto layout and size classes. The problem only occurs near the bottom of the tableview, maybe last 20% of the table. – trapper Oct 10 '17 at 07:53
  • I'm seeing the same problem (lower portion of the tableview only). I've submitted a bug report to Apple about this issue. I made a very simple example app to replicate the problem and it seems as though there isn't much we can do on our side to solve this. I'll be setting estimatedSectionHeaderHeight to 0 for the time being as that solved my problem. Example project here for those interested: https://github.com/szweier/iOS11TableViewBug – Steve Oct 13 '17 at 15:10
  • I'm having the same issue as well. Any update/fix on your side? – GrizzlyBear Nov 28 '17 at 10:54
  • I keep thinking it's my manual layout code issue. This solve the bug for me, thanks! – DazChong Jan 05 '18 at 15:49
7

In iOS 11.2, I had a bad animation after deleting a row using the standard row actions. I was only able to improve the situation by wrapping the row delete and row action dismissal in a CATransaction.

I dismiss the row actions first and wait for that animation to complete before deleting the row from the table view.

It at least doesn't jump around the table views content offset anymore, but is a lengthy two step animation. I'm still looking for a better solution.

        CATransaction.begin()
        CATransaction.setCompletionBlock({
            self.tableView.beginUpdates()
            self.myViewModel?.items?.remove(at: indexPath.row)
            self.tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.top)
            self.tableView.endUpdates()
        })
        self.tableView.setEditing(false, animated: true)
        CATransaction.commit()
6

I had similar problem with table row removal animation on iOS 11 sometimes scrolling the table cells strangely (iOS 10 worked just fine). What helped was implementing this delegate method returning row height:

- (CGFloat) tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath

After that both iOS 10 and 11 work just fine.

Chuck Boris
  • 1,275
  • 1
  • 11
  • 9
4

I fixed it by using this code:

self.tableView.beginUpdates()
// ...
self.tableView.endUpdates()
self.tableView.layer.removeAllAnimations()
Piotr Merski
  • 101
  • 4
1

A partial fix that is working for me is setting estimatedRowHeight to a large number.

tableView.estimatedRowHeight = 1000
Vlad
  • 5,727
  • 3
  • 38
  • 59