3

I have a NSManagedObjectContext set to have a NSPrivateQueueConcurrencyType which I'm using most of the time across my app.

As well as this I created a child MOC with NSMainQueueConcurrencyType for use with cocoa bindings (I hear that bindings don't work with private queue MOCs). I have bound some ObjectControllers and an ArrayController to this child context. I very much want to keep the child on the main queue rather than swapping the MOC queue types.

When I make changes to the bound objects via UI, the changes don't propagate up to the parent context. And when I make changes to the parent context, they don't filter down to the Object/ArrayControllers.

How can I make this happen? Is there a setting that will tell the Object/ArrayControllers to refresh their context appropriately and save it when they make changes?

Mark Wheeler
  • 587
  • 2
  • 6
  • 19

1 Answers1

6

To bring changes to the parent, you need to save the child. If you want to save the changes persistently, you also need to save the parent after that.

[child save:&error];
[parent performBlock:^{
    [parent save:&parentError];
}];

To bring changes from parent to the child, you need either merge changes using a notification method from parent's NSManagedObjectContextDidSaveNotification or re-fetch in child context. Merging is probably better in your case.

- (void)managedObjectContextDidSave:(NSNotification *)notification {
    // Here we assume that this is a did-save notification from the parent.
    // Because parent is of private queue concurrency type, we are
    // on a background thread and can't use child (which is of main queue
    // concurrency type) directly.
    [child performBlock:^{
        [child mergeChangesFromContextDidSaveNotification:notification];
    }];
}
eofster
  • 2,027
  • 15
  • 18
  • Doesn't this mean that every time I adjust a property of an object via the parent MOC I need to call it's save method in order to propagate the changes? Is that not going to slow things down a bit as they will go into the persistent store? – Mark Wheeler Jul 09 '13 at 14:38
  • Your parent context is of private queue concurrency type. Everything you do there, including saves, will be run on a background queue. It won't block your main thread, but it will lock the context and the persistent store coordinator, however this might not be a problem for you. – eofster Jul 09 '13 at 16:46
  • Thanks, this was a really helpful answer. I hooked up appropriate IBActions to trigger the child saves when needed and the rest was pretty straightforward. – Mark Wheeler Jul 11 '13 at 05:02
  • I couldn't get re-fetching in the child context to work, but merging changes does. Does anyone know what might cause that? – Symmetric Jan 13 '14 at 04:27
  • What exactly isn’t working? For example, you fetch the object in the child, then update it (change some property) in the parent, then fetch again in the child. Because the object was already a fully realized object, the second fetch doesn’t touch it, it just returns it in its current state. That’s just how Core Data works. It doesn’t touch fully realized objects automatically. However when you call -mergeChangesFromContextDidSaveNotification:, the property of the object will be updated, because you manually asked for the merging. – eofster Jan 13 '14 at 13:26