8
votes

Not sure if this is an issue with the way Magical Record does saves, or I'm just making an noob mistake somewhere.

I'm using an NSFetchedResultController (FRC) and UITableView to display a list of entities, when the user taps "Add" a new View Controller with an editor is pushed, a new entity is created with [MyEntity MR_createEntity]. The user can add additional entities here that are added to the main entity via a relationship. When the user taps "Save" in this View Controller the context is saved using [[NSManagedObjectContext MR_contextForCurrentThread] MR_save]

The NSFetchedResultsController appears to update, but when I tap to edit the entity none of the child entities are there. Debugging seems to show that even though the entity has been saved the FRC still has the entity with it's temporary ID.

I'm doing a naive [self.tableView reloadData] in the FRC controllerDidChangeContent delegate method.

Restarting the application loads the correct entities and the child entities are show properly in the editor view controller.

It looks like the FRC responds to the "main thread" save event, but the save is actually happening on a background thread so the FRC doesn't see it. I've checked and all "my" operations (setting up the FRC, creating and fetching entities) are all happening on the main thread context.

I tried listening for change notifications on MR_rootSavingContext and merging them with the main thread context, which sort of worked but I ended up with duplicates rows in the FRC (one was the correct "permanent" entity and one was the temporary one).

2

2 Answers

8
votes

OK, I'm not sure if this is "the right way to do it" but I've found that it works correctly if I created my NSFetchedResultsController in the MR_rootSavingContext instead of the default context using the "inContext" version of MR_fetchAllSortedBy.

I guess this makes sense from the point of view that the FRC is now watching the rootSavingContext instead of one of it's children. Still, I would have thought since I'm doing all my operations on the same thread that wouldn't be an issue.

Update: The only gotcha with this approach is that if I just grab the entity using [frc objectAtIndexPath:] to give it to the editing view controller then it's no longer in the default context. Worked around this by re-fetching the entity in the default context using NSManagedObjectContext's existingObjectWithID. Still doesn't all feel quite right, but it's working for me.

0
votes

Aware this is an old answer but none of the above worked for me and hopefully will help future readers

For me the problem was caused by trying to setup a purely local store using a sqlite file that had previously been used with iCloud.

Basically I tried to implement iCloud with my CoreData app, did the basic steps to set it up with an ubiquity container etc but then reverted back because of the inherent instability this seemed to cause (why is it that CoreData and iCloud STILL dont get along?!), but cocoa doesn't like you backtracking like that.

Fortunately I haven't done this in a live app so it's relatively easy to change as it will only affect development devices, but if you're moving from iCloud to a local store in a live app I think you might need to check out one of these solutions:

Migrating a Core Data Store from iCloud to local