NSManagedObjectContext and NSArrayController reset / update problem

I'm having trouble getting my user interface to reflect external changes (made by another process) in the sqlite data store.

I have a standard base view of NSArrayController / table based on master data. My application receives a notification that external changes have been made to the data, after which I do

[managedObjectContext reset]; // brute force, but data set is small 

The problem is that this clears all the data from the table. An array controller placed in objects is also empty. I thought the next

 [arrayController fetch:nil]; 

may help, but it is not. Executing a fetch request in the managedObjectContext file indicates that the data is present and updated, so managedObjectContext is aware of the changes.

Any tips on how to โ€œrestoreโ€ from reset? Or maybe the reset approach is completely wrong, in which case is there a better way to load external changes?

+4
source share
2 answers

I do not think that two projects should work in one Core Data database. It is probably best to let one process act as a server that owns (and opens) the database and allows others to send commands to make changes. I donโ€™t think that Core Data has always been intended to support several processes talking to the same db.

+1
source

So, I played with this particular situation, and I will not contradict the first answer - you probably shouldn't do this, and if you need it, iCloud might work. Do not use this code. I provide it to help others get to the point that they can detect all the problems that I have not fixed, and move on.

However, you can do what the original question wanted to ask - to force the controller to reboot from disk:

 // Tear down bindings and context, create new context & rebind [self.watcherAC unbind:@"managedObjectContext"]; [self saveAction:self]; // Optional, dependent on NSMergePolicy, etc self.managedObjectContext = [[NSManagedObjectContext alloc] init]; self.managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; [self.managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator]; [self.watcherAC bind:@"managedObjectContext" toObject:self withKeyPath:@"managedObjectContext" options:nil]; // Force controller to refetch and rearrange NSError* error; [self.watcherAC fetchWithRequest:nil merge:NO error:&error]; // Immediate fetch [self.watcherAC prepareContent]; [self.watcherAC rearrangeObjects]; 

This updates the contents of the tableView from storage on disk. (TableView is bound to watcherAC array controller)

I found that fetch: is not immediate - this was done the next time through the launch loop for the application. So that the fetch / swap is done in the correct order, you need to use fetchWithRequest:

I'm not sure if readyContent: is needed, although it may have helped fix errors in the contents of the controller.

I was not able to get it to restore the selection of tableView, although it may be because I am doing this in a delegate call to tableview, so the choice of the view does not synchronize with the choice of the controller no matter what attempts I try. Maybe this might work for someone, but I suggest trying to figure out how not to allocate a new MOC if your view has bindings to it.

0
source

All Articles