You can't do this directly in Core Data because, unlike your example above, Core Data has to maintain the relationship graph as well.
To understand this, suppose you setup relationships manually using the example code above. Now imagine that you have a SavedDie
class that is saved in the savedDice
and immediateRolls
of PlayerState
. If you want each SavedDie
instance to refer to the PlayerState
, creating a pointer to the owning PlayerState
would be easy but how could you tell which PlayerState
property it was stored in. More importantly, how could you enforce it such that the same SavedDie
object didn't end up in both properties or in two or more separate PlayerState
objects?
Core Data was created to manage all this automatically and it uses the entity graph to do so. Entities are not classes. Instead they are an abstract representation primarily of the relationships between objects. The entity graph won't let you have the one entity have two relationships to another entity because it would be impossible to keep track of which instances of the live data objects went with each other.
There are two ways to solve your problem.
(1) Use entity inheritance: You create an Die
entity and set it up with all the attributes you want it to have. Then you create two subentites: SavedDie
and ImmediateDie
. Then you set relationships:
PlayerState.savedDie<-->SavedDie.playerState
PlayerState.immediateDie<-->>ImmediateDie.playerState
(2) Use fetched relationship: In this case, you have one Die
entity and one relationship:
PlayerState.Die<-->>Die.playerState
... but you have an attribute of Die
that makes each instances as saved or immediate. Then you create two fetched relationships whose predicates each look for different states of the flag.
(3) Use a link entity: In this technique, you use an intermediate entity to tie the two main entities together in multiple relationships like so:
PlayerState{
//...some attributes
savedDice<-->>PlayerToSavedDie.playerState
immediateDice<-->>PlayerToImmediateDie.playerState
}
ToDie{
die<-->SaveDie.player
}
PlayerToSavedDie:ToDie{ //...subentity of ToDie
//... no attributes
playerState<<-->PlayerState.savedDice
}
PlayerToImmediateDie:ToDie{ //...subentity of ToDie
//... no attributes
playerState<<-->PlayerState.savedDice
}
Die{
player<-->ToDie.die
}
This way you can move a Die
instance around relationships just by deleting one link relationship and creating another. Since the Die.player
points to ToDie
it will accept either PlayerToSavedDie
or PlayerToImmediateDie
in that relationship.
Which one of these techniques you use depends on the needs of your data model. If the logical Die objects in one relationship never jump to the other, use (1). If the saved or immediate data is an important attribute of the logical Die objects themselves, use (2). If the logical Die objects need to move between relationships and saved or immediate data is not part of the logical Die object, then use (3).
All this might seem a lot of work but you have to remember one import thing: Relationships are just as import as attributes! A model will not work if its relationships do not reflect the real world objects, events or conditions the model simulates. You should expect to spend sometime thinking about and managing relationships.
Core Data makes relationship management a hundred times easier but it still takes some work.