Suppose I have an entity MeetingNote with standard attributes plus a one to many relationship to another entity Tag.
Out of MeetingNote instances, I want to create instances of another entity called Task but only in case meetingNote.tag.name == 'task' is TRUE.
What do you think would be the correct way of modelling the relationship between Task and MeetingNote? Or should there be a relationship at all and I ought to use a fetched property with the appropriate predicate instead?
Firstly, the true purpose of Core Data is not persistence but rather to create the model layer of a Model-View-Controller design app. That means that Core Data is really a model/simulation API first and a persistence API second. A Core Data data model, therefore, should accurately represent the attributes of real-world objects, conditions or events and the relationships between them.
So, when you set down to build a data model, you should forget about the UI, the data source or any other implementation details and simply try to create a model that mirrors the real-world objects, conditions or events the app deals with.
Secondly, while a data model deals with how entities are related, it doesn’t deal with the logic of why the entities are related. That logic is belongs in code somewhere often in the custom NSManagedObject subclasses for the entities. In this case, the how of the entities relationships is that the
MeetingNoteentity is related to bothTaskandTags. The why is that there should be a relationship between any particularMeetingNoteobject and anyTaskobject only if theMeetingNoteobject has a relationship to aTagobject with the name oftask.So, your basic data model should look like this:
Now the question becomes one of where to stick the custom logic for the why. The most logically simple way would be to create a custom accessor for
MeetingNote.tagsproperty that checks if name of a tag being added or removed to anMeetingNote instanceequalstaskand if so, adding or removing aTaskobject from the instance’sMeetingNote.tasksrelationship.However, that has an obvious performance penalty of having to check every tag added or removed. A better solution would be to add the custom to only one point that is called only when the exact condition of
MeetingNote.tags.name' contains a value oftask`.Let’s assume you have the following constraints:
MeetingNoteobject cannot have a relatedTaskobject without also having aTag object with name=="task".MeetingNoteobject does have aTag object with name=="task"it must have at least one relatedTaskobject.MeetingNoteobject looses its relationship to aTag object with name=="task", then it loses all its task.It is immediately obvious at this point that `Tag object with name==”task” is a special object with behaviors different from other tags. This justifies and requires that it have its own entity and subclass so we would add to the data model:
Since the
TaskTagentity inherits from theTagentity it can automatically inherits the in theTag.meetingNotesrelationship so it will behave as aTagobject from the perspective of anyMeetinNoteobjects.Then in the
TaskTagNSManagedObject subclass we would add the following code:This code will automatically enforce the constraints above without having to do anything else. You could also customize the
Tasksubclass to set its name automatically based on some attributes of theMeetingNoteobject it is related to.Now you have all the why logic in the data model and your constraints are automatically enforced. This may not be the exact solution you need but you get the idea.