Snowman
Snowman

Reputation: 32071

How to model my Core Data entity?

I want to store NoteObjects in Core Data. Normally, a NoteObject has a NSString *mainText and an NSMutableArray *arrayOfTags (an array of NSStrings). I want to now use Core Data, but arrays are a tricky matter with core data. Typically a NoteObject won't have more than 50 tags in its array. So how should I model this? I have two options:

  1. Use a transformable property to store the array
  2. Use a to-many relationship, which I've read is the more "legit" way to do it.

Which one should I use and why? And how would I implement a to-many relationship with my simple structure? I can't seem to wrap my fingers around that concept.

Upvotes: 0

Views: 171

Answers (3)

Eugene
Eugene

Reputation: 10045

Use to-many relationship. Because it's way better and easier during fetch requests. See the screenshots below. Pay attention to the Relationship manager on the right side, set "To-Many Relationship" from your NoteObject to Tags. Ignore the Player entity.

Oh and pay attention to the "Delete Rule". You might want to delete all the tags associated with a given NoteObject. So set it to Cascade in that case.

NoteObject entityenter image description here

Tag entityenter image description here

--Edit:

To add multiple tags you need to first fetch your NoteObject - I assume there will be some sort of ID parameter which you'll use to distinguish NoteObjects. CoreData will automatically generate the add/remove methods for Tags. You'll need to use code similar to the one below:

- (void)addTags:(NSArray *)tags toNoteObjectWithID:(NSString *)noteID {
  NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"NoteObject"];
  NSPredicate *pred = [NSPredicate predicateWithFormat:@"noteID == %@", noteID];
  [fetchRequest setPredicate:pred];
  NoteObject *noteObject = [[[self managedObjectContext] executeFetchRequest:fetchRequest error:nil] lastObject];

  for (NSString *tag in tags) {
    Tag *t = [NSEntityDescription insertNewObjectForEntityForName:@"Tag"
                                           inManagedObjectContext:[self managedObjectContext]];
    t.body = tag;
    t.noteObject = noteObject;
    [noteObject addTagsObject:t];
  }
  [self saveContext];
}

Upvotes: 4

Caleb
Caleb

Reputation: 124997

Arrays were only tricky in Core Data because they weren't supported prior to iOS 5, so you had to include some attribute (like creation date) by which they could be sorted. If you don't mind requiring iOS 5, you can use ordered relationships. Results are returned in an NSOrderedSet, which is a lot like (and can can be converted to) an array. Or, just re-think the problem -- is the order of the tags on a note important to the note or the user? Would it be okay if you just display the tags in alphabetical order? If so, even better -- just use a plain old (unordered) to-many relationship.

Upvotes: 1

DRVic
DRVic

Reputation: 2481

You could use a transformable property, but then you need to write the transformer.

If you use a toMany relationship, you have to create an additional entity for tags, which presumably has only one attribute - the string value, and a single relationship. Extrapolating a little, I would guess that you have a finite set of values tags can take on, and you might someday want all notes that have tag X - then you would be able to fetch the entity containing the string value for X and then use that to fetch the NSArray of objects that have X in the relationship (whatever you called it).

Upvotes: 1

Related Questions