views:

57

answers:

1

Dear iphone developers,

Core Data newbie speaking here.

In my application I have two NSManagedObjectContext that refer to that same NSPersistentStorageController.

One ManagedObjectContext (c1) is in the main thread --created when I create a NSFetchedResultsController -- and the second ManagedObjectContext (c2) created in a second thread, running in the background, detached from the main thread.

In the background thread I pull some data off a website and insert the entities created for the pulled data in the thread's ManagedObjectContext (c2).

In the meanwhile, the main thread sits doing nothing and displaying a UITableView whose data do be display should be provided by the NSFetchedResultsController.

When the background thread has finished pulling the data and inserting entities in c2, c2 saves, and the background thread notifies the main thread that the processing has finished before it exiting.

As a matter of fact, the entities that I have inserted in c2 are know by c1 because it can ask it about one particular entity with [c1 existingObjectWithID:ObjectID error:&error];

I would expect at this point, if I call on my tableview reloadData to see some rows showing up with the data I pulled from the web in the background thread thanks to the NSFetchedResults controller which should react to the modifications of its ManagedObjectContext (c1).

But nothing is happening! Only if I restart the application I see what I have previously pulled from the web!

Where am I doing things wrong?

Thank you in advance!

A: 

Reloading the table will not refetch items from the persistent store as you are expecting. Reloading the table is a "UI" level action and fetching data is at the model level. While this is fine for any changes that occur in the main NSManagedObjectContext, this will not cause the main NSManagedObjectContext to become aware of changes that occurred in another NSManagedObjectContext.

Depending on your design you need to do one of the following:

  • When the main thread receives the notification on the background thread's save it needs to call -mergeChangesFromContextDidSaveNotification:.
  • When this is complete you need to save the main NSManagedObjectContext
  • During the save it will trigger your NSFetchedResultsController with changes
  • The NSFetchedResultsController will notify its delegate (normally your view controller) of the changes and give you an opportunity to update the table view.

I suspect that you are not doing one of those items and thus breaking the chain of events.

Example

There is a solid example of multi-thread notifications in my article over on the MDN. If you are not familiar with the MDN, I highly suggest taking a look.

Marcus S. Zarra
I am sorry, nothing of this is working. Probably I also did that wrong. Basically I followed this http://stackoverflow.com/questions/2637141/core-data-multi-threading.But I found I solution to my problem. Once my background thread has finished I just call the performFetch method of the NSFetchedResultsController again with a new predicate. Obviously I have the feeling this is wrong but I can't manage to find information on how to do it the correct way, as you suggested.
tmpz
Recalling perform fetch is a solution yes but an expensive one. I would suggest reviewing your code and making sure your `NSFetchedResultsController` has its delegate set and that you have implemented the delegate methods.
Marcus S. Zarra
My NSFetchedResultsController (on c1) has its delegate set (the same object that owns it) and I did implement the delegate methods, in fact if i save c1 the -controllerDidChangeContent: method I wrote gets called correctly.Could you be so kind to point me to an example of what you suggests as a solution? I mean a concrete example using -mergeChangesFromContextDidSaveNotification:Thank you in advance.
tmpz