Reputation: 4552
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"
Upvotes: 1
Views: 104
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
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
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