David
David

Reputation: 7456

tableView.reloadRows flickers if called too quickly after another table update

This video demonstrates the issue I'm visually having.

Every so often, I have this block called:

self.tableView.beginUpdates()
self.tableView.insertRows(at: [indexPath], with: rowAnimation)
self.tableView.endUpdates()

self.tableView.scrollToRow(at: indexPath, at: scrollPosition, animated: true)
self.tableView.reloadRows(at: [indexPath], with: .automatic)

Let us not interrogate it too much (the insertRows call and an immediate reloadRows call). This was the suggested solution to solving a bug in the SlackTextViewController. The bug in question for those curious.

Now, elsewhere, I call:

self.tableView.reloadRows(at: [indexPath], with: .automatic)

When we're handling the same indexPath in both situations, you'll come across a flicker if those two blocks are run too quickly.

I would find it very hacky to go about artifically delaying the second call of self.tableView.reloadRows(at: [indexPath], with: .automatic) by using the dispatchQueue(:asyncAfter) method.

How could I approach this?

Update: For now, I have fixed this by using the dispatchQueue(:asyncAfter) method in a way that avoids race conditions. I'd like to avoid this though, so I'll keep this up as I search for other answers.

Upvotes: 3

Views: 974

Answers (1)

Hong Wei
Hong Wei

Reputation: 1407

Based on your comment, if the second call happens in a completion block after a network call, I am guessing you are using the result of a network call. If this is the case, if the change you need to reflect in the cell does not affect the height of the cell, you can just get the cell at index path, check if it is nil (in case the user scrolled it off screen) and apply the change directly if the cell is still visible. No reloading required.

Upvotes: 3

Related Questions