0

When implementing a custom NSMergePolicy, there are 3 functions available to overload:

final class MyMergePolicy: NSMergePolicy {

    override func resolve(mergeConflicts list: [Any]) throws {
        // ...
        try super.resolve(mergeConflicts: list)
    }

    override func resolve(optimisticLockingConflicts list: [NSMergeConflict]) throws {
        // ...
        try super.resolve(optimisticLockingConflicts: list)
    }

    override func resolve(constraintConflicts list: [NSConstraintConflict]) throws {
        // ...
        try super.resolve(constraintConflicts: list)
    }
}

Documentation for all 3 is exactly the same, it says: "Resolves the conflicts in a given list.", and I can't seem to find much information online.

What's the difference between these functions? What are the appropriate use cases for each of them?

Andrii Chernenko
  • 9,873
  • 7
  • 71
  • 89

1 Answers1

1

The documentation kind of sucks here but you can get a partial explanation by looking at the arguments the functions receive.

  • resolve(optimisticLockingConflicts list: [NSMergeConflict]): Gets a list of one or more NSMergeConflict. This is what you'll usually hear about as a merge conflict, when the same underlying instance is modified on more than one managed object context.
  • resolve(constraintConflicts list: [NSConstraintConflict]): Gets a list of one or more NSConstraintConflict. This happens if you have uniqueness constraints on an entity but you try to insert an instance with a duplicate value.

The odd one out is resolve(mergeConflicts list: [Any]). This one is basically a leftover from the days before uniqueness constraints existed. It gets called for both types of conflict described above-- but only if you don't implement the more-specific function. So for example if you have a constraint conflict, resolve(constraintConflicts:...) gets called if you implemented it. If you didn't implement it, the context tries to fall back on resolve(mergeConflicts list: [Any]) instead. The same process applies for merge conflicts-- the context uses one function if it exists, and can fall back on the other. Don't implement this function, use one of the other two.

For both conflict types, the arguments give you details on the conflict, including the objects with the conflict and the details of the conflict. You can resolve them however you like.

Tom Harrington
  • 69,312
  • 10
  • 146
  • 170
  • Thank you for the answer! The documentation sure is sorely lacking, and I can't seem to find any good examples of a custom `NSMergePolicy` implementation either. Another important piece of knowledge that's missing is what Core Data is expecting after these methods are called. What does it mean to "resolve a conflict"? Am I expected to delete the conflicting objects I don't want? Or should I determine the correct values of each attribute and relationship and update all conflicting objects accordingly? – Andrii Chernenko Oct 18 '22 at 11:55
  • You can do anything you want so long as the result means that the incoming conflicts won’t exist with your changes. – Tom Harrington Oct 19 '22 at 02:16