Core Data: Forcing Propogation of Changes

I just encountered a situation where I was added NSManagedObject instances to a context and the data did not automatically show up in a bound NSArrayController/table view. I think there's an elusive bug to be found here, but the workaround is to do this:

NSManagedObjectContext * context; // assume this exists
NSManagedObject * newObject;

newObject = [NSEntityDescription
               insertNewObjectForEntityForName: @"Person"
               inManagedObjectContext: context];

// force updates to be sent to bound controllers

[context processPendingChanges];


The -processPendingChanges: forces the changes to be processed immediately instead at the end of the current event. Don't get trigger-happy and use it all the time, it's just a workaround if things are acting strange. Also, be aware that it could affect the behavior of automatic undo/redo.
Design Element
Core Data: Forcing Propogation of Changes
Posted Nov 18, 2005 — 4 comments below




 

Alex R — Nov 20, 05 555

I had a similar experience. With an arraycontroller bound to a treecontroller which was bound in turn to yet another arraycontroller. Looking at the resulting xml file showed that managed objects where being added to the context but they were not showing up in the table view.
Any idea what conditions cause this failure?

Scott Stevenson — Nov 21, 05 556 Scotty the Leopard

Not sure what causes it. Wish I knew!

Hannes Petri — Jun 04, 06 1348

A while ago, I tried to write a snippet-management-application, where you added pieces of text by dropping it on the dock icon. However, the text titles didn't show up in the table view, until I moved the window or something like that. A friend helped me solve it this way:

Put this in the init-method of the document:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(managedObjectContextUpdatedNotification:) name:NSManagedObjectContextObjectsDidChangeNotification object:[self managedObjectContext]];

And add the method like this:

-(void)managedObjectContextUpdatedNotification:(NSNotification *)notif
{
NSDictionary *userInfo = [notif userInfo];
NSSet *inserted = [userInfo objectForKey:NSInsertedObjectsKey];
if (yourArrayController && inserted && [inserted count]) {
[yourArrayController setSelectedObjects:[inserted allObjects]];
}
}

Mike Margolis — Oct 10, 06 2026

Sorry if this is a bit late, I only saw this post today :)

For performance reasons, processPendingChanges: only gets called automatically after event processing in the runloop. It would be too expensive to call it after every single notification, timer invocation, etc. If you are changing your managed object context in response to anything but direct user input you must call processPendingChanges: manually for changes to take effect. Do not abuse this call, it can dramatically slow down your application if, for example, you call it after every single object creation, insertion, modification, or deletion... it is best to do all of your work in a batch before calling processPendingChanges:.

Some examples of when this is needed include a worker thread finishes loading some data and adds new data to the core data managed object context. (Of course, you did add that new data from the *main* runloop, correct?) , or a notification or timer gets triggered and you update some value.

The UI (and many internals of your app) will be out of sync with the expected state of the database....er... object-graph management and persistence thingamagigger (don't call it a database, the core data folks hate that :-D) until the user starts clicking around on the UI... at which point weird unexpected behavior might occur. My suggested approach would be to have the main thread load and process the data that was obtained in the [worker thread/posted notification userinfo / etc] and then have call [moc processPendingChanges:] before returning.

Hopefully this helps, it has saved my butt many times in the past and understanding why this is needed and how often to call it has helped keep my core data apps fast with a consistent 'database'.




 

Add Your Thoughts

Use UBB tags: [b] [i] [url] [code], and so on
Use [i] for quoting: [i]Quoted Text[/i]
Omit double quotes in links: [url=http://apple.com]Apple[/url]
Accented characters are currently stripped from names



Please enter the company who makes the Mac:
this is an anti-spam measure
Some comments may be edited for formatting, or removed if too far off-topic.




Technorati Profile
Copyright © Scott Stevenson 2004-2008