0

I have to say that everyone on the forum has been really helpful with my attempts at learning core data.

I am adding attribute values to my core data entities and creating a relationship when the user selects a row as shown below:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{

UIAlertView *messageAlert = [[UIAlertView alloc]
                                 initWithTitle:@"Row Selected" message:@"Added to Routine!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];

    NSManagedObjectContext *context = [self managedObjectContext];

    // Create a new device
    ExcerciseInfo *info = [_fetchedResultsController objectAtIndexPath:indexPath];
NSManagedObject *routineEntity = [NSEntityDescription insertNewObjectForEntityForName:@"Routines"inManagedObjectContext:context];
NSManagedObject *routineEntityDetail = [NSEntityDescription insertNewObjectForEntityForName:@"RoutinesDetails" inManagedObjectContext:context];

[routineEntityDetail setValue:routineEntity forKey:@"routineinfo"];

    [routineEntity setValue: RoutineText  forKey:@"routinename"];
    [routineEntityDetail setValue: info.details.muscle  forKey:@"image"];

How would I include an IF statement whereby if the routinename already exists the new entry would be added to the existing relationship?

Is this easily possible from the current code? So the Test Routines will be grouped instead of showing separately and the detail view would include both entries. Would NSPredicatebe appropriate here? Or perhaps the use of distinctUnionOfObjects?

You thoughts and comments will be appreciated.

enter image description hereenter image description here

AS REQUESTED -

- (NSFetchedResultsController *)fetchedResultsController {

    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription
                                   entityForName:@"Routines" inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc]
    initWithKey:@"routinename" ascending:NO];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

    [fetchRequest setFetchBatchSize:20];

    NSFetchedResultsController *theFetchedResultsController =
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                        managedObjectContext:managedObjectContext sectionNameKeyPath:nil
                                                   cacheName: nil];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;
Sgillon
  • 147
  • 12
  • Can you share your `ManagedObjectModel`? Is `RoutineDetails` in a one-to-many relationship with `RoutineEntity`? – nikolovski Jul 10 '13 at 15:52
  • @MarkoNikolovski I have updated the question. Yes the entities are in a 1-to-many relationship. I have included a snap shot of the entities.Thanks – Sgillon Jul 10 '13 at 15:58

1 Answers1

0

You don't need to care about this, you can simply insert a new RoutineDetails object and Core Data takes care of the rest. When you auto-generate the NSManagedObjectsubclasses of your DB tables, Core Data automatically generates accessor methods for all relationships, where you can add and remove single or multiple instances of RoutineDetails from Routines.

To create NSManagedObject subclasses, go to your ManagedObjectModel click on Editor->Create NSManagedObject subclass… and create subclasses for your entities:

Create subclasses

In your new subclass, you'll see methods like:

@interface Routines (CoreDataGeneratedAccessors)
- (void)addRoutineDetailsObject:(RoutineDetails *)value;
- (void)removeRoutineDetailsObject:(RoutineDetails *)value;
- (void)addRoutineDetails:(NSSet *)values;
- (void)removeRoutineDetails:(NSSet *)values;

Than you can access all the RoutineDetails directly through the Routines object (you'll get an NSSet of RoutineDetails), and furthermore you can add new objects with

[routineEntity addRoutineDetailsObject:routineEntityDetail];

not caring if an object already exists or not. Core Data will do the right thing.

Comment regarding Core Data: Core Data can have a lot boilerplate code for simple things like fetching. Take a look at the MagicalRecord project, which is much less verbose and does wonders.

EDIT: Whenever you previously created NSManagedObject, now you can directly use your own classes, i.e. Routines. That way you'll have access to all the "new functionality".

nikolovski
  • 4,049
  • 1
  • 31
  • 37
  • Hi Marko, thanks for the great answer. The only issue i'm getting now is it is saying `No visible @interface for 'NSManagedObject' declares the selector addRoutinedetObject`. I have never worked with subclasses before. – Sgillon Jul 11 '13 at 10:02
  • Did you create the `NSManagedObject` classes? Also, don't forget to include them in the `.m` file. – nikolovski Jul 11 '13 at 10:10
  • Ah, and also when you create objects instead of: `NSManagedObject *routineEntity` use `Routines *routineEntity` – nikolovski Jul 11 '13 at 10:11
  • Hi Marko, yeah I created the classes when I made the entities. Thanks for the help. It still creates individual entries every time the row is click and doesn't group them. The detail view still works but I presume the way you suggested is more efficient than the way I previously did it. I'm not sure if the way I am adding the routines is flawed as the excercises are added when u click a row and the routine name is stored in a string and added too. You have cleared up my understanding of subclasses though! – Sgillon Jul 11 '13 at 10:59
  • Hi Marko, I have decided to accept your answer as you have cleared up a few issues for me and worked hard to help me. thank you. – Sgillon Jul 11 '13 at 12:08
  • Thanks! Do you want to group `RoutineDetails` by which `Routine` they are in? – nikolovski Jul 11 '13 at 12:43
  • Yeah, I am looking to group all `RoutineDetails` by which `Routine` they are in. So all RoutineDetails with a relationship to the same Routine will be grouped. Like `Routine` called **Test** with `RoutineDetails` **Crunch** and **Chest Press** will be grouped in the detailview – Sgillon Jul 11 '13 at 12:47
  • And this detail view is a big table view with all the `RoutineDetails`? – nikolovski Jul 11 '13 at 13:00
  • yeah the detail view contains the associated RoutineDetails displayed in a UITableView – Sgillon Jul 11 '13 at 13:19
  • Well, given an array of `Routine` objects, the `numberOfSections:` would be the `routineArray.count`; the `numberOfRowsInSection:` would be the `routineArray[section].details.count` (`details` is the `NSSet` of `RoutineDetails` corresponding to a `Routine`) and than you can wire up everything as needed in the `tableView:cellForRowAtIndexPath:`. – nikolovski Jul 11 '13 at 14:00