user2786037
user2786037

Reputation: 505

Core Data ensuring data uniqueness

I've been working with Magical record and Core Data for a while, but still I can't figure out how to ensure object uniqueness.

Assume I have a function:

- (void) foo {
    [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
        // find if model with x = myValue exists
        MyModel *model = [MyModel MR_findFirstWithPredicate:[NSPredicate predicateWithFormat:@"x = %@", myValue] inContext:localContext];

        // if there is no model - create it!                          
        if (!model) {   
            model = [MyModel MR_createInContext:localContext];
            model.x = myValue;
            // etc...
        }
    }];
}

Everything goes fine until foo is called twice (or 3, 4...etc times). Now localContext doesn't know about localContext in other thread and uniqueness checks passes. As a result after context merge I have 2 (3,4...etc) instances with given value (instead of 1).

How can I ensure only 1 object with given value exits?

PS. —validateValue:forKey:error: won't help, as it called BEFORE context merge (during saving object).

Upvotes: 0

Views: 135

Answers (2)

Mundi
Mundi

Reputation: 80271

I guess one approach would be to check before merging and alter or delete the duplicate values. You can do this by listening to the NSManagedObjectContextWillSaveNotification and making the changes before calling mergeChangesFromContextDidSaveNotification.

Upvotes: 1

casademora
casademora

Reputation: 69757

The reason this doesnt work after a few loops is that the saveWithBlock method is dispatching queues under the covers for you. Because of this, each local context is a fresh new context. Each localContext is unaware of the contents in any of the others created by your loop. This means the findFirst method will return nothing every time and create a new, but duplicate copy of the model object. The way to fix this is to either,

  • do all the looping inside the saveWithBlock method
  • create your own context and use that for all your data saves in the loop

The idea is to use the same context for all your operations so you can look up data in the context. And in some cases that data will be your newly created and unsaved data.

Upvotes: 0

Related Questions