BlackMouse
BlackMouse

Reputation: 4552

Core data: Insert and delete with To many relationship

I'm making a simple diary app with core data.

The main model (Journal) will contain a title and a body. Each entry can have one or many tags.

To insert a new (Journal), I just do this:

Journal *newJournal  [NSEntityDescription insertNewObjectForEntityForName:@"Journal"
                                             inManagedObjectContext:context];
//Save 

Question 1: What's the correct way to add tags to the entry?

I could do this:

Tag *tag1 = [NSEntityDescription insertNewObjectForEntityForName:@"Tag"
                                             inManagedObjectContext:context];
Tag *tag2 = [NSEntityDescription insertNewObjectForEntityForName:@"Tag"
                                             inManagedObjectContext:context];
newJournalEntry.tags = [[NSOrderedSet alloc] initWithObjects:tag1,tag2,nil];
// Save card... 

... but that will create new tags for every entry. I only need unique instances of each tag in the core data model.

Question 2: How do I query journal entries by tags, e.g "Get all journal entries that has a fun tag"

I also need get all created tags and display them, e.g: "You have 3 tags: Fun, sport, vacation"

enter image description here

Upvotes: 1

Views: 104

Answers (2)

vbali
vbali

Reputation: 805

First of all, you will need a many-to-many relationships between Journal and Tag models, otherwise you won't be able to assign the same Tag to multiple Journal entries

enter image description here

Answer 1: before assign any tags to the Journal entry, fetch the existing tags from the store:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Tag"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"name IN %@", @[@"tag1", @"tag2"]];
NSArray *tags = [moc executeFetchRequest:fetchRequest error:&error];

Then you should create tags with -insertNewObjectForEntityName only for the missing tags.

Answer 2:

NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Journal"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"tags CONTAINS[cd] %@", @"fun"];
NSArray *journalEntries = [moc executeFetchRequest:fetchRequest error:&error];

You can read more about predicates in Predicates Programming Guide

Upvotes: 1

Ares
Ares

Reputation: 5903

Answer 1: You need to change your model to many-to-many between your tags and your journalEntry then you need to query your model to see if the tags already exist. If they do, then you just link them to your entry entity.

Example (in Pseudo Code):

NSOrderedSet tags = nil;
//Create and fetch for the tags you are looking for. Then:

 if([[FetchedResultController fetchedObjects] count] > 0) {

     tags = [[NSOrderedSet alloc] initWithArray:[FetchedResultController fetchedObjects]];

 } else {
   //The code you actually have (almost)
   Tag *tag1 = [NSEntityDescription insertNewObjectForEntityForName:@"Tag"
                                         inManagedObjectContext:context];
   Tag *tag2 = [NSEntityDescription insertNewObjectForEntityForName:@"Tag"
                                         inManagedObjectContext:context];
   tags = [[NSOrderedSet alloc] initWithObjects:tag1,tag2,nil];
 }

 //Then just set your tags
 newJournalEntry.tags = tags;

Answer 2: Once you have implemented Answer one then you look for those tags and then just use the relationship to the journalEntry (e.g.: tags.journal) which should be an a NSSet.

Again Pseudo code:

for(Tag *tag in [FetchResultController fetchedObjects]) {

       //Get the Journal Entries using:  "tag.journal" 
      NSSet *journalEntriesWithTagRequested = tag.journal;

      // Do what you must with journalEntriesWithTagRequested . . .

   }

Upvotes: 1

Related Questions