Merge policy matters when you're trying to save changes but there are other changes that were saved somewhere else-- like another thread, or CloudKit importing some data. For example,
- You fetch an object
- You make changes to the object but haven't saved changes yet
- A different thread changes the same object, with different changes than the ones you just made
- You try to save changes
How does Core Data combine your unsaved changes with the new changes in the persistent store? It depends on your merge policy. By default, the merge policy is NSErrorMergePolicy, which means that you can't save changes because of the conflict. You have other choices, though.
Apple's descriptions are short and to the point, so an example would probably help with understanding them. Suppose you have a Person entity and the properties are name, address, phone, and birthday. You fetched one instance and you're editing it, and another thread saves changes that conflict with your edits. It might look like this:
| Property |
Original |
Your change |
Other thread change |
name |
Taylor Swift |
Taylor Jones |
Taylor Swift |
address |
123 Main St |
123 Main St |
123 Sesame St |
phone |
(212) 555-1212 |
1-800-275-2273 |
(650) 253-0000 |
birthday |
Electronica |
Electronica |
Electronica |
Now you try to save changes, so what happens? How does Core Data resolve your changes vs. the other thread's changes? The built-in merge policies provide some options.
Two of them merge "by property", which means Core Data looks at each property value and chooses one valueor the other. NSMergeByPropertyStoreTrumpMergePolicy means that when the values are different, the value in the persistent store wins. NSMergeByPropertyObjectTrumpMergePolicy means the value in memory wins. [In these policy names, "trump" means outranking or winning, so it might be easier to think of them that way. Imagine that they're named NSMergeByPropertyStoreWinsMergePolicy and NSMergeByPropertyObjectWinsMergePolicy.] These only change values when there's a conflicting change. In the table above, that happens for phone.
This is what happens when saving with those policies:
With NSMergeByPropertyStoreTrumpMergePolicy, the persistent store wins when there's a conflict.
| Property |
Resolved value |
Explanation |
name |
Taylor Jones |
No conflict, your change is used |
address |
123 Sesame St |
No conflict, store change is used |
phone |
(650) 253-0000 |
Conflict! Merge policy says the store wins |
birthday |
Electronica |
No changes |
With NSMergeByPropertyObjectTrumpMergePolicy, in-memory changes win the conflict:
| Property |
Resolved value |
Explanation |
name |
Taylor Jones |
No conflict, your change is used |
address |
123 Sesame St |
No conflict, store change is used |
phone |
1-800-275-2273 |
Conflict! Merge policy says the your change wins |
birthday |
Electronica |
No changes |
The others-- NSOverwriteMergePolicy and NSRollbackMergePolicy-- also mean that one version or the other wins. But for these two the policy can make changes even if conflicts don't exist. One or the other wins completely. In the table above, there are non-conflicting changes for name and address because only one version changes the original value, and of course there's a conflicting change for phone again.
Here's what happens with those merge policies:
With NSOverwriteMergePolicy, your in-memory changes win out everywhere, even if there's no conflicting change.
| Property |
Resolved value |
Explanation |
name |
Taylor Jones |
No conflict, your change is used |
address |
123 Main St |
No conflict, but merge policy says your change wins |
phone |
1-800-275-2273 |
Conflict! Merge policy says your change wins |
birthday |
Electronica |
No changes |
With NSRollbackMergePolicy it's the opposite: the persistent store wins everywhere, even if there's no conflicting change.
| Property |
Resolved value |
Explanation |
name |
Taylor Swift |
No conflict but merge policy says the store wins |
address |
123 Sesame St |
No conflict, persistent store value is used |
phone |
(650) 253-0000 |
Conflict! Merge policy says the persistent store wins |
birthday |
Electronica |
No changes |
If none of these do what you want, you can subclass NSMergePolicy and write your own policy, by implementing resolve(mergeConflicts: [Any]) and maybe some other functions.