Search code examples
ioscore-datanspredicatensfetchrequest

Can two CoreData entities have more than one "to-many" relationship between them?


My model has an entity "Filter" and an entity "Color". I want to have two "To-Many" relationships between them: "backgrounds" and "foregrounds". (i.e. each "Filter" contains an array of background colors, and an array of foreground colors, all of type "Color").

I have two problems. First, when I set up the relationships the inverse from "Color" can only have one value (I'm guessing this means I can't do what I want). Second, I can't figure out how I would create a predicate to fetch only the backgrounds or only the foregrounds. I assume the following will return all of them merged together (if it worked at all):

NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Color"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"filter == %@", self];

I'm about to solve this by converting Color into two Foreground and Background entities, but I don't want to do that without understanding why a single entity won't work. Am I missing something here?

NOTE: This apparently is not intuitive to me. I came across this exact problem again, but this time I wasn't using predicates so I didn't find the problem right away. I had a very similar setup, but when I tried to remove a child it would initially go away, but when I restarted my app in would reappear more than once. The more children I removed, the more I ended up with. I eventually noticed the same children were in both relationship arrays, and when I looked at the graphical version of the model, only one of the relationships had an arrow connected to the child. Finally, I remembered I'd had this problem before! I don't understand well what was happening, but apparent the two child "arrays" where merged together in a weird way.


Solution

  • Yes.

    Theory about multiple to-many relations

    Say you have the entity CHILD which is either a boy or a girl. Each child can have a set (to-many) of all their siblings. But each child could also have two more sets (to-many) of all their 1: brothers and 2: sisters.

    The reverse relation of "siblings" would be "isSiblingTo" (or siblings). And the reverse of "brothers" and "sisters" would be "isBrotherTo" and "isSisterTo".

    This was very simple since both entities where the same.

    Say instead I am a child who has a set of crayons and a set of toys. I probably have my red crayon in both these sets, i.e. I have to to-many relations to it.

    It all boils down to that the red crayon is both my CRAYON and my TOY. As with the sibling example above, a child's brothers are both their siblings and their brothers and their sisters are both their siblings and their sisters.

    Update:

    You don't need to be a part of both relations. You can have a child without the siblings relation but with both the brothers and sisters relations and the other children would have the reverse relations to them (this is closer to your color+filter example)

    Applied on your example

    So, if you have a use for it, it is doable. Just think of their relations in day-to-day language and set the reverse as isForegroundColorTo and isBackgroundColorTo.

    data model with multiple to-many relations data model with multiple to-many relations

    color model definition color model definition

    filter model definition filter model definition