I have a core data stack that only explicitly uses the main context, and only makes changes to/creates persistent objects within a context.performAndWait block. If I ever need a background context, I always use the following code block:
persistentContainer.performBackgroundTask()
{context in
context.performAndWait
{
defer
{
context.save()
persistentContainer.context.save()
}
//make changes here
}
}
The main context's merge policy is set on the creation of the persistentStore, to NSOverwriteMergePolicy, which, when I save the background context, I expected to overwrite any "old" objects on the main context with any "new" objects created in a background context. Instead what is happening is I'm getting a NSConstraintConflict error, because the background context uses the default merge policy (not sure why, I expected it to inherit the merge policy of the main context.) When I explicitly set the background context's merge policy, I end up with duplicates of objects that there should not be duplicates of according to the constraints I'm setting. In this case, the clientID attribute must be unique for any given Client entity.
I feel like I'm somehow not merging the contexts properly. The way I'm doing it now is just by saving the background context, and then the main context, more or less as shown above. But if I wasn't merging properly, why would a constraint error occur when there are objects created on a background context that have the same attributes as objects in the main context? And why would the duplicates be appearing when I do a fetch request on the main context?
I'm only about two months in on using core data and everything I know came from documentation or here, so I'm sure there is something I'm just ignorant about. Any ideas as to what I'm doing wrong?
Turns out I had not set the constraint for the entity I was seeing duplicates of. Setting the constraint got rid of the duplicate objects.
To solve the issue with the NSConstraintConflict errors whenever I saved on the background contexts, I made all background contexts created with the function I was using have the same merge policy, using the following custom class:
When initializing my data store in the custom PersistenceManager class: