8

I've been studying Core Data quite a bit now, and I've now decided it's time to use it in a new project I'm doing.

Having never use it in a working project I've just come across a few issues I would like to get the communities feedback on.

I'm doing a location based application and I would like to store "outings" in my Core Data model, so for each trip I have some traditional information such as date, distance, description etc... But I also need to save location information which I'll need to plot some points on a map.

So I have a "to" and "from" object per trip, I've created a MapPoint entity with latitude, longitude and location name attributes. On my Trip entity, I've added a "to" and a "from" relationship who's destination is MapPoint.

But what do I do with the inverse property?

Because Xcode seems to give a warning it I leave it as "No inverse".

I needed to create 2 relationships on MapPoint to reference back to the Trip to the "to" and another relationship referencing the "from" relationship of Trip.

Is this correct ? I can't quite understand.

I have a similar issue with a User Entity where this is being used in several other Entities, should I be implementing an inverse relationship back to each Entity which uses User?

To keep Xcode happy it seems I need to create a relationship on User back to Trip, and back to other Entities I'm using such as an Upload, Picture entities etc... it seems to me disturbing to think a Trip has a User object, which would then have prepared to link back to an Upload/Photo... which has nothing to do with that Trip.

Daniel
  • 23,129
  • 12
  • 109
  • 154

3 Answers3

9

If you want to support inverse relationships for your to and from relationships, you can just add appropriate relationships to your MapPoint entity. Call them tripTo and tripFrom, or whatever seems appropriate to you, and set those as the inverse relationships for your to and from relationships, respectively.

As the docs explain, you're not required to model a relationship in both directions, but doing so makes life easier. What happens, for example, when a user is deleted? If you have a number of other entities related to User, then you need some way to figure out which objects were related to that user so that you can update them. If you have inverse relationships, Core Data can automatically update any related objects using the deletion rule (like nullify) that you choose. Without inverse relationships, it's up to you to fix up any related objects.

Caleb
  • 124,013
  • 19
  • 183
  • 272
  • 1
    I have CountryEntity. It has two relations. 1. `capital` with a `CityEntity` destination—type _one to one_ 2. `cities` with a `CityEntity` destination— type _one to many_. Can you elaborate how I should set the inverse part. Because apparently only either `capital` or `cities` can have a relation – mfaani Dec 07 '18 at 15:58
  • @Honey This sounds like it should probably be a separate question rather than a comment, but I can't think of a reason why those relations couldn't each have an inverse. – Caleb Dec 07 '18 at 16:11
3

I'm not entirely familiar with Core Data, but I believe it has a form of entity inheritance.

You could make your MapPoint entity abstract and create a FromMapPoint and a ToMapPoint which inherit their attributes from the MapPoint entity.

Your Trip entity can then have two separate relationships - one to FromMapPoint and one to ToMapPoint with the appropriate inverses.

As I said - I'm no CD expert, so hopefully someone else can come along and validate/shoot-down this suggestion?

With a bit of digging I found that you can set the parent entity through the Data Model Inspector. I created this quick representation of what you've been talking about.

Maurice Kelly
  • 1,462
  • 12
  • 15
  • Doesn't seem like as clean a solution as the other answer, but I gave you thumbs up for originality. – morningstar Sep 12 '11 at 16:39
  • Thanks. I was going for more of a OO approach. Personally I would prefer not to have empty relationships - e.g. if a `MapPoint` was a To point, then it's `tripFrom` relationship will be incomplete. Just a personal preference though! – Maurice Kelly Sep 12 '11 at 19:38
  • +1 for your answer, cause I hate the idea of multiple inverse relationships for the same object. *However*, your solution is exactly the _same_ as the accepted one, because inheritance don't really exist in SQLite: if you look inside your `.sqlite`, all your sub-entities will be aggregated in a big one, with null values in the keys that are not shared with every entity. – Martin Oct 22 '14 at 16:31
  • Inheritance is excellent for fetching though. It’s best to model the data how it will be fetched and displayed using the fetched results controller. – malhal Oct 13 '17 at 01:10
3

In my experience Core Data doesn't "require" you to have inverse relationships, but not having them leads to mysterious bugs, even if you make sure to keep your object graph consistent manually. At least I think that's what was causing the mysterious bugs.

The SQLite store uses inverse relationships to represent to-many relationships. For a to-many relationship foo from entity A to entity B, I would have thought it would create a separate table "foo" with a column A and a column B, with object ids appearing more than once in column A. Nope. It doesn't represent one-to-many relationships at all, it represents their inverses only, which are to-one relationships. It represents fooInverse as a column in entity B's table, containing object ids that correspond to A-type entities. So you must have an inverse. It seems that in simple cases Core Data can deduce what the inverse should be if you don't define it, and your to-many property works correctly. However in more complicated cases such as the one you describe, it falls over.

morningstar
  • 8,952
  • 6
  • 31
  • 42