Leon
Leon

Reputation: 3726

Why does storing a reference to an NSManagedObject prevent it from updating?

This question is poorly phased but this can be better explained in code.

We have a Core Data Stack with private and main contexts as defined by Marcus Zarra here: http://martiancraft.com/blog/2015/03/core-data-stack/

We call a separate class to do a fetch request (main context) and return an array of NSManagedObjects:

NSArray *ourManagedObjects = [[Client sharedClient].coreDataManager fetchArrayForClass:[OurObject class] sortKey:@"name" ascending:YES];

We then do some processing and store a reference:

self.ourObjects = processedManagedObjects

Our view contains a UITableView and this data is used to populate it and that works just fine.

We change the data on our CMS, pull to refresh on the UITableView to trigger a sync (private context) and then call this same function to retrieve the updated data. However, the fetch request returns the exact same data as before even though when I check the sqlite db directly it contains the new data. To get the new values to display I have to reload the app.

I have discovered that if I don't assign the processedManagedObjects to self, the fetch request does indeed return the correct data, so it looks like holding a reference to the NSManagedObject stops it from getting new data from the main context. However I have no idea why that would be.

To clarify, we're pretty sure there's nothing wrong with our Core Data Stack, even when these managed objects are not being updated, other are being updated just fine, it's only this one where we store a local reference.

Upvotes: 1

Views: 331

Answers (2)

pbasdf
pbasdf

Reputation: 21536

Try setting the shouldRefreshRefetchedObjects property of the fetch request to true. According to the documentation:

By default when you fetch objects, they maintain their current property values, even if the values in the persistent store have changed. Invoking this method with the parameter true means that when the fetch is executed, the property values of fetched objects are updated with the current values in the persistent store.

Upvotes: 0

Tom Harrington
Tom Harrington

Reputation: 70966

It sounds like what's going on is:

  • Managed objects don't automatically update themselves to reflect the latest data in the persistent store when changes are made via a different managed object context.
  • As a result, if you keep a reference to the objects, they keep whatever data they already had.
  • On the other hand if you don't keep a reference but instead re-fetch them, you get the new data because there was no managed object hanging around with its old data.

You have a few options:

  • You could keep the reference and have your context refresh the managed objects, using either the refresh(_, mergeChanges:) method or refreshAllObjects().
  • If it makes sense for your app, use an NSFetchedResultsController and use its delegate methods to be notified of changes.
  • Don't keep the reference.

The first is probably best-- refreshAllObjects() is probably what you want. Other options might be better based on other details of your app.

Upvotes: 2

Related Questions