April 26, 2020

NSFetchedResultsController - ignore add/remove change for a relationship attribute

2 minutes read



Requirement

Two entities in Core Data named CompanyEntity and PriceEntity. They are connected via one-to-many relationship.

App downloads data in background - seperate feeds for companies and prices. I rigged up application to download different data feeds, to quickly debug and see how UI reacts when a company goes away and/or it appears again in feed. UI uses NSFetchedResultsController to monitor changes and update tableView. All changes are animated.

While implementing these requirements, I noticed “a bug” or rather - an unforseen functionality.

If I only download company data - it is correctly reflected. Companies which names are updated, are refreshed with animation.

So far so good.

Problem started appearing when I rigged up to download different price feeds (full & empty, for testing). In this case, I decided to always delete old prices instead of updating them by id, thus - in Core Data, I always remove old ones and add any new ones that are found in the feed. This means - for Companies, it’s “prices” relationship will change all the time.

Turns out - a relationship acts the same as any attribute - NSFetchedResultsController will notify about it when it changes and my tableView is “updated” every time this “relationship” attribute is changed.

Disabled company feed downloading, enabled prices downloading.
TableView simply reloads cells, for which "prices" relationship was updated.

Problem is - in companies tableView, I am not interested in this relationship attribute “prices”, as I only want to show actual Company data. So I would prefer that tableview would update only to reflect changes for CompanyEntity main attributes.

Solution

I ended up using a “metadata” entity.

Simply put - it connects our main entities - CompanyEntity and PriceEntity in a way, that a company still can get to it’s prices, and any price still has access to it’s company.

But this way - my Companies tableView is not updated anymore, when prices are removed/added.

P.S.

If I had chosen to use tableView.reloadData() I probably would not have noticed this issue. And even with such “glitch”, in my app’s real life scenario, it might have not been any issue at all (how often do I need to download prices, and the chance of that happening while I am looking at companies list…). But still, it is nice to find out such problems and figure a solution or two, for good measure!