IanCZane
IanCZane

Reputation: 640

How to set merge policy in Swift 4 CoreData

I'm attempting to update an entity in CoreData. Here are some of my declarations.

static var appDelegate = UIApplication.shared.delegate as! AppDelegate
static var context = appDelegate.persistentContainer.viewContext
static var entity = NSEntityDescription.entity(forEntityName: "PData", in: context)
static var newPData = NSManagedObject(entity: entity!, insertInto: context)

I'm somewhat certain the fact that they're static isn't relevant.

PData is the name of the entity (short for persistent data).

Later on, I set the values I'd like to save using newPData.setValue("foo", forKey: "bar"), but when I actually attempt to save them with context.save(), I get NSCocoaErrorDomain Code 133020 "Could not merge changes."

I should mention that this is meant to occur directly after deleting an existing entry in PData (replacing an old entity instance with a new one).

I've done some reading, and I've found that the reason for this error is that the default way that Swift handles a CoreData merge conflict is to throw an error. I'd like to change my CoreData settings such that changes from memory overwrite changes already stored within the entity in CoreData, but I'm not sure as to how I'd going about doing this.

The Apple documentation shows lots of different merge policy options, but doesn't have an example showing how to implement them. I think the one I need to use is NSMergeByPropertyStoreTrumpMergePolicy, but I have no idea how to actually set said policy as the merge policy.

Upvotes: 11

Views: 7795

Answers (4)

Harish Rathuri
Harish Rathuri

Reputation: 72

In Swift 5 once you create a project with Core Data, then you have Persistence.swift file in your project directory. In this class put mergePolicy code in the last of init() function.

init(inMemory: Bool = false) {
   ....
  
   container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
}

And it's work for me 😉.

Upvotes: 2

IanCZane
IanCZane

Reputation: 640

I found the answer - to set the context's merge policy, you simply do

context.mergePolicy = NSMergePolicy(merge: NSMergePolicyType.mergeByPropertyObjectTrumpMergePolicyType)

I was getting tripped up by trying to do

context.mergePolicy = mergeByPropertyObjectTrumpMergePolicyType)

but I guess it's necessary to spawn an NSMergePolicy object. I just assumed that the actual merge policy (mergeByPropertyObjectTrumpMergePolicyType) would be of the correct type by default.

Upvotes: 18

Pravin
Pravin

Reputation: 61

Merge policies are used in coredata to resolve the conflict issue between persistent store and different managed object context, it depends on you which merge policy is suitable for your application. As from the code snippet it seams that you are using single managed object conext. Please try below code-

appDelegate.persistentContainer.viewContext.automaticallyMergesChangesFromParent = true
appDelegate.persistentContainer.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyStoreTrump

Upvotes: 1

asharijuang
asharijuang

Reputation: 529

You can put mergePolicy when initiate persistentContainer

var persistentContainer: NSPersistentContainer = {
        let modelURL = Bundle.main.url(forResource: DB_NAME, withExtension: "momd")!
        let container = NSPersistentContainer.init(name: DB_NAME, managedObjectModel: NSManagedObjectModel(contentsOf: modelURL)!)
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
            if let error = error as NSError? {
                QiscusLogger.errorPrint("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()

Upvotes: 7

Related Questions