NSFetchedResultsController

This could probably come under the heading of my iOS 7 Diary, but it’s not, so there.

NSFetchedResultsController has been with us for a while. At first glance it seems a pretty handy class to have about the place. But there’s a lot of information floating about on the internet about it being a bit buggy and unreliable. I decided to put it to the test.

Step forward, The NSFetchedResultsController Stress Test. It’s a chaos monkey for pseudo-randomly modifying a simple Core Data model. After each iteration, the fetched results controller is interrogated to see if it’s correctly kept up. You can run the tool for as long as you like, but if there is a bug, it does tend to fail fairly quickly.

The controller is hooked up to drive a table view. I’ll discuss that aspect more in a later article; for now let’s just focus on the data structures vended out by NSFetchedResultsController.

There are quite a variety of ways to configure a fetched results controller. Happily, after testing a great deal, I can report that for almost all of them, on iOS 7.1.1, the controller performs as expected. There is just one curious edge case I’ve discovered:

Sections

Configure the stress test as follows:

The model consists of objects holding a random number between 0 and 99. The results are sorted by that number, and then sectioned according to the first digit. Numbers over 49 are excluded by a predicate.

At each iteration, up to 2 new objects are inserted, and there’s a chance any of the existing objects will have their number changed, or be deleted.

After running for about a minute and a half (you can lower the editing interval to speed this up!), STRICT_SECTION_OBJECTS_CHECK fails, which is rather curious.

What have we ended up with? Well, bizarrely, one of the controller’s sections claims to contain just the one object (as according to .numberOfObjects), but when you query .objects, there actually turns out to be an extra one after that! Furthermore, this extra object is found to not even belong in this section (it shows up twice, in both correct and wrong sections). rdar://17436358

Hmmmm, this seems a pain. As far as I can tell though, this isn’t actually a showstopper though. If we treat .objects with some distrust, the bug can be worked around:

Turning off STRICT_SECTION_OBJECTS_CHECK in my stress test effectively does this. Fascinatingly, following iterations continue to work fine, making this really quite a weird glitch!

I expect most apps are following Apple’s lead of implementing table data sources along these lines:

Fortunately this means your table view won’t be affected by the bug, since the table will only query as far as the objects you’ve told about. My workaround above should rarely be needed in its direct form; it’s intended to demonstrate the problem more than a concrete solution.


So there you go, that’s the non-UI side of my NSFetchedResultsController testing. Feel free to try fiddling with the tests yourself, and let me know if you discover any other oddities.

Update: Part 2 is now up, looking at integration with UITableView.

© Mike Abdullah 2007-2015