Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 770
IanCZane Avatar asked May 05 '18 21:05

IanCZane


People also ask

What is merge policy?

Merging policies enables you to create multiple policy attachments at an attachment point, resulting in a merged policy that is created and attached at this interface. Executing more than one policy attachment command with the same attachment type at an interface triggers a policy merge through the CLI.

How do I use Coredata?

Use Core Data to save your application's permanent data for offline use, to cache temporary data, and to add undo functionality to your app on a single device. To sync data across multiple devices in a single iCloud account, Core Data automatically mirrors your schema to a CloudKit container.

What is NSManagedObject in core data?

In some respects, an NSManagedObject acts like a dictionary—it's a generic container object that provides efficient storage for the properties defined by its associated NSEntityDescription instance.


2 Answers

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.

like image 113
IanCZane Avatar answered Nov 04 '22 01:11

IanCZane


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
    }()
like image 28
asharijuang Avatar answered Nov 04 '22 01:11

asharijuang