Unique Core Data Limitations - "Spoofing Reference to Invalid Object" when Saving

I present unique constraints for an existing application in the new version of the model.

The model has a Person object that has an optional one-to-one relationship with the Pet object. The person deletion rule is cascaded, and the Pet feedback deletion rule is canceled. There is another entity, Job, which also has one relationship. But this deletion rule and the reverse deletion rule are not valid.

A person has a personID property, which I made unique.

In the context of the main queue, I have an instance of Person, with ID xxx, which does not have a Pet set. Let me call this man Charlie. I also create a Job and set it as "iOS Dev" and assign it a Charlie job property.

Then, in the context of the child private queue, I insert a new "Charlie" also with the identifier xxx (unique constraint) and create a Pet and set it. I do not ask a job. I maintain a detailed context without problems.

Immediately after this, I try to maintain the context of the main queue. But before that, I check the insertObjects property of the Main Queue context and see, as I expect, an instance of Person with ID xxx. I expect this second instance to be handled by unique constraints and to be “merged” with the original Person instance from the previous paragraph. But, when I actually call the MOC save method: it throws an exception, and I check the NSError object:

Domain Error = NSCocoaErrorDomain Code = 1550 "Operation could not be completed. (Cocoa error 1550.)" UserInfo = {Hanging link to an invalid object. = null

Any ideas on how to avoid the exception? I'm used to the “cheated links” in Core Data, which means the relationship is incorrect, but I looked at it many times and everything looks fine, so I'm not sure what else needs to be fixed. I have all the contexts associated with the NSMergeByPropertyObjectTrumpMergePolicy merge policy.

Obviously, this is a bit complicated, so I threw a sample project on Github in case anyone is interested: https://github.com/bpapa/core-data-unique-bug

+5
source share
3 answers

I ran Code-Level Support on this ticket, and an Apple engineer confirmed that there was an error. As a workaround, it was recommended to write my own merge policy, which calls super, and then manually, to make sure the relationship is established at both ends.

+4
source

If you want to use the new iOS 9 Unique Constrains strategy, you must make sure that both contexts have the same merge policy .

Note that this will not be the case if you have a scenario where a new instance of the object has the nil attribute / relationship, and your intention is to always "increase" the object, i.e. Fill in all missing attributes and update existing ones.

Otherwise, for pre-iOS9, the following is valid.

There may be some misunderstanding regarding the meaning of the merge policy you are using ( NSMergeByPropertyObjectTrumpMergePolicy ). This applies when you have one version of an object in memory and the other in persistent storage, rather than two versions in memory in different contexts. From the header files:

This singleton policy combines conflicts between the persistent version of the object store and the current version in memory.

Thus, your process of creating a new object is not correct.

Instead, you should get Person in the child context using a unique identifier.

Alternatively, you can make the objectID face available for the child context (an opaque artifact of the master data) to get a reference to the same object in the object graph using objectWithID:

+1
source

Merge the changes into the main context using the saved notification from the background context. See Earthquakes Apple Sample.

0
source

Source: https://habr.com/ru/post/1247219/


All Articles