iOS 11 UITableView performBatchUpdates completion closure not being called

Greg Anderson picture Greg Anderson · May 22, 2018 · Viewed 7.5k times · Source

I have a UITableView which is displaying an aggregated feed of posts from several RSS feeds. Whenever my app pulls new posts from a feed, I create an object representing all of the needed insertions and deletions needed to update the UITableView current rows. I place these objects into an array which I use as a FIFO queue. Every few seconds, I pull the first element out of this array and attempt to perform all of the insertions and deletions within the UITableView using the function UITableView:performBatchUpdates.

This all works great ... so long as the user doesn't scroll the UITableView up and down. If there is scrolling going on, the updates will cease, because I am setting a flag to ensure that I always wait until the last set of insertions/deletions has completed before I start the next batch, and sadly, sometimes, the completion closure of UITableView:performBatchUpdates never gets called, hence my flag is never cleared.

Here is the code I'm using to process my incoming queue of changes for the UITableView:

@objc func updateFeedPostsTableView() {

    guard feedUpdateQueue.count > 0,
          !feedTableUpdateInProgress else { return }

    feedTableUpdateInProgress = true
    let feedUpdate = feedUpdateQueue.first!
    feedUpdateQueue.remove(at: 0)

    self.aggregatedRSSFeed = feedUpdate.feed

    self.feedPostsTableView.performBatchUpdates ({
        self.feedPostsTableView.deleteRows(at: feedUpdate.indexPathsOfDeletedPosts,
                                           with: .fade)
        self.feedPostsTableView.insertRows(at: feedUpdate.indexPathsOfNewPosts,
                                           with: .top)
        },
        completion: { (success) in
            self.feedTableUpdateInProgress = false
        }
    )
}

My question is, why would UITableView.performBatchUpdates ever fail to call its completion block? What am I doing wrong here?

This is iOS 11.2, using Xcode version 9.2.

Thanks!

Answer

iamiend picture iamiend · May 22, 2019

I was having this problem. The main performBatchUpdates block was getting executed but the completion block was never called. I found out that the issue was caused by me using a subclass of UITableView. As soon as I switched back to a vanilla UITableView the problem went away.

Lesson learned. Don't subclass UITableView.