Reputation: 1703
I've implemented CloudKit
into my iOS App using the NSPersistentCloudKitContainer
.
While doing this, I came across the NSMergePolicy
.
I searched for an explanation for the different options, however, the Apple Developer Documentation
wasn't very helpful.
NSErrorMergePolicy
NSMergeByPropertyStoreTrumpMergePolicy
NSMergeByPropertyObjectTrumpMergePolicy
NSOverwriteMergePolicy
NSRollbackMergePolicy
Question: Can anyone explain, what the difference between these Policies is (if possible with examples)? And should I use the default on (NSErrorMergePolicy
) or change it?
Upvotes: 8
Views: 1477
Reputation: 70976
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,
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 value or 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.
Upvotes: 35