Cescy
Cescy

Reputation: 1991

Fetch an one-one relationship Entity's attribute?

I am unable to fetch the results of a 1-1 relationship Entity's attribute?

BACKGROUND INFO

I have three UITableViewControllers, The grandfather TVC has 10 cells, Day 1, Day 2..Day 10. The father TVC has 3 cells, Workout 1, Workout 2, Workout 3. And in the child TVC I set the attributes of each workout and its "workoutscore". So each day Cell has 3 workoutcells after segue.

Workout1, Workout2, Workout3 each have a workoutscore attribute. I would like to display the workout score on the workout cells.

So I have a Day Entity with a one-one relationship with Workout1 Entity with Workout2 Entity and Workout 3 Entity.

Day <---> Workout1       Day<----->Workout2     Day<---->Workout3

After back navigation from the child to parent I correctly pass the workoutscore and save the context in the parent. The labels on the WorkOut cells correctly display the workoutscore.

Of course when I navigate back to the grandfather TVC and back to parent the parent TVC deallocs and I would like to fetch the previous scores based on the Day of the Grandfather TVC.

SAVING APPEARS IN VIEWDIDAPPEAR (This is correct)

In the parent TVC (Note: I am only showing the code for one workout as it is the same for the other 2)

AppDelegate *ad = [[UIApplication sharedApplication] delegate];

Day *myDay = [NSEntityDescription insertNewObjectForEntityForName:@"Day"
                                                     inManagedObjectContext:ad.managedObjectContext];

Workout1 *myWorkout1 = [NSEntityDescription insertNewObjectForEntityForName:@"Workout1"
                                                           inManagedObjectContext:ad.managedObjectContext];

NSNumber *theNumber = myWorkout1.workoutscore; //get old score
theNumber = [self updateNumber:theNumber forIndex: 11];
myWorkout1.workoutscore = theNumber; //update for new score
[myDay setWorkout1:myWorkout1]; //set Workout Entity to day Entity

NSError *savingError = nil;
myDay.dayname = [NSString stringWithString:self.dayname];
[ad.managedObjectContext save:&savingError];
}

FETCHING APPEARS IN VIEWDIDLOAD (This is incorrect, something is not working here)

In the parent TVC (Note: I am only showing the code for one workout as it is the same for the other 2)

     AppDelegate *ad = [[UIApplication sharedApplication] delegate];

Day *day = [NSEntityDescription insertNewObjectForEntityForName:@"Day"
                                           inManagedObjectContext:ad.managedObjectContext];

Workout1 *myWorkout1 = [NSEntityDescription insertNewObjectForEntityForName:@"Workout1"
                                                           inManagedObjectContext:ad.managedObjectContext];

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Workout1" inManagedObjectContext:ad.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObjects:@"Day",nil]];
[fetchRequest setIncludesSubentities:YES];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"day.daynumber contains %@", self.dayLabel.text]; //self.dayLabel.text is Day# in string form.
[fetchRequest setPredicate:predicate];

NSError *error = nil;

NSArray *fetchedObjects = [ad.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
    NSLog(@"Nothing was fetched");
}
NSLog(@"number of fetched objects is %lu", (unsigned long)[fetchedObjects count]);

myWorkout1 = [fetchedObjects lastObject]; //most recent update of score

if ([fetchedObjects count] > 0) {
       stringWS1 = [[NSMutableString alloc] init];
       stringWS1 = [NSMutableString stringWithFormat:@"%@",myWorkout1.workoutscore];
        self.workoutScoreLabel1.text = [NSMutableString stringWithString:stringWS1]; //Put score on label

Before the If statement of [fetchedObjects count] > 0 all I get is (null) on the labels. Now i get nothing because the array == 0. yet I save correctly?.

Upvotes: 0

Views: 58

Answers (1)

Dan Shelly
Dan Shelly

Reputation: 6011

You have so many issues here its really hard to point in the right direction.

  1. CoreData does not have a built-in method for "create-or-update". when you call insertNewObjectForEntityForName:inManagedObjectContext: you are introducing a new object to the context. this mean that in your current state you are inserting an empty Day and WorkoutX in every viewDidLoad call of the "parent TVC". this also happens in your viewDidAppear, but there you set values for your inserted objects.
  2. Your fetch request could be much simpler if you'd send the Day.objectID to the "parent TVC", your predicate will be: [NSPredicate predicateWithFormat:@"day = %@",dayObjectID]
  3. Why are you splitting the Workout entity to 3 separate entities? You could have a single Workout entity and 3 to-one relationships in the Day entity (or a to-many relationship if you like to have a variable number of workouts).
  4. Keep references to what you are updating (day, workout) and update directly these objects (as long as you work only on the main thread there is no need to get them by their ID)
  5. read the CoreData documentation HERE, specifically about creating, deleting and fetching managed objects.
  6. look at some examples (like a blank CoreData project in Xcode), and see how they work with objects.

Upvotes: 1

Related Questions