Menu & Search

Fixing a broken UITableView linked with Core Data

October 5, 2015

A week ago, I helped out a fellow iOS developer struggling with a table view that was acting really weird. Basically the table view getting data from the fetched results controller wasn’t displaying all of the rows that were stored in Core Data. I was curious.

At first, he sent me a short gist. I looked around and everything looked fine. I checked:

  1. Is the NSManagedObjectContext set up properly?
  2. Is the NSFetchedResultsController set up properly?
  3. How is the UITableView getting the number of sections and rows?

Everything looked fine, but the app still wasn’t displaying the correct number of rows and all the ones that were off-screen weren’t being configured. Now I was becoming really curious.

I asked for the complete project and started digging around. I was putting NSLogs and breakpoints everywhere. Everything seemed fine but what I did notice was that cellForRowAtIndexPath wasn’t being called once the table view was scrolled down a bit. That was really strange, because numberOfRowsInSection was indeed returning the proper row count.

“THIS IS SO WEIRD” I thought.

Then I noticed something. You see, when you hook up your table view with fetched results controller, you should never have to call tableView.reloadData(). If you configured it properly, the table view should get “reloaded” automatically. But how you might ask. Because if you implement the callback methods of the NSFetchedResultsControllerDelegate, it should all be taken care of.

Here are the methods:

Notice the tableView.beginUpdates() call in the controllerWillChangeContent? Well, the UITableView documentation states the following:

Call this method if you want subsequent insertions, deletion, and selection operations (for example, cellForRowAtIndexPath: and indexPathsForVisibleRows) to be animated simultaneously. You can also use this method followed by the endUpdates method to animate the change in the row heights without reloading the cell. This group of methods must conclude with an invocation of endUpdates. These method pairs can be nested. If you do not make the insertion, deletion, and selection calls inside this block, table attributes such as row count might become invalid. You should not call reloadData within the group; if you call this method within the group, you must perform any animations yourself.

The app that was behaving weirdly didn’t have the corresponding endUpdates call, but that wasn’t apparent to me from the start. Of course I wasn’t paying attention to that, because it’s mostly boilerplate code. So again boys and girls:

  1. Do not forget to implement ALL NSFetchedResultsControllerDelegate delegate methods if you want your table view to behave properly and do not forget to call tableView.endUpdates() if you’re calling tableView.beginUpdates().
  2. Do not call tableView.reloadData()  between beginUpdates() and endUpdates()!

An almost-one-liner and too much time later, we got the app up and running and displaying data from Core Data nicely!


Take part in the 5-day course with actionable tasks that will let you become a master at recognizing and solving the most common mistakes iOS developers do with Auto Layout.

Let Auto Layout become a tool you swing with your utmost confidence!

I won't send you spam, I promise. Unsubscribe at any time. Powered by ConvertKit
Hey there! You're already subscribed to my newsletter and you've hopefully gotten some useful tips and tricks when working with iOS. If you're also working with Auto Layout, make sure to check out my book called Auto Layout Fundamentals and get a 20% off for being my subscriber!
Jure Zove

A lot of things but mostly a programmer who really likes fast cars. Check me out on Twitter, if you fancy.

Related article

Introducing The “How do I Auto Layout” Cheatsheet


Fastest way to use Auto Layout in code

Raise your ✋ if you hate adding views and setting…

Swift Optionals Demystified


Type your search keyword, and press enter to search