I had the same problem. In my case, this happened when I was doing unit tests. In this case, there were two main data stacks in memory, one for the wiring harness, and the other for my unit tests being tested.
The first key to solving this issue was to put a statement right before setting the relation property to make sure that the entity type of the object that I set was the same as the expected relation entity type. They should be the same, and in my case they were not.
In my case, I had a MatchRequest
that had a one-to-one relationship with a Player
called an "initiator". So, my statement was as follows:
let player = try Player.findLocal(for: matchRequest.initiator, in: moc, createIfMissing: true) let expectedEntity = self.entity.relationshipsByName["initiator"]!.destinationEntity! assert(player!.entity === expectedEntity, "Player returned doesn't have the same entity type") self.initiator = player
The above statement failed, which I suspect is similar to the statement used by Core Data, which throws an argument exception.
When checking Player.entity (), it returns the same instance of the object that causes the crash.
I think the root of the problem is that Core Data sets some kind of static property for entities that will not be correctly distributed between the main data stacks. The call to MyManagedObject.entity () will work correctly when called from one stack, but not in another.
So, to get around the problem, when I create a Player object for input into relationships, I get the object using the older API NSEntityDescription.insertNewObject(...)
, and not the newer constructor MyManagedObject(context:)
. This ensures that the correct object is used for the given context of the managed object.
So, to repeat:
// SOMETIMES FAILS if you have more than one core data stack: result = Player(context: managedObjectContext) // ALWAYS WORKS: result = NSEntityDescription.insertNewObject(forEntityName: "Player", into: managedObjectContext) as? Player