iCode
iCode

Reputation: 1466

Core-Data NSFetchedResultsController to-many relationship

Here is my Datamodel: Datamodel

I filled the Database with Data.

Now I want to display this in a tableview. First I want to select a day with the 'days' attribute, then get its lessons. I want to display the attributes 'end' and 'start' in the header (-(NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section)

Then I want to display the lesson data in the right section. How can I do that with NSFetchedResultsController?

I've set up a basic code:

NSFetchRequest* fetch = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([Lessons class])];

NSSortDescriptor* sortGroup = [NSSortDescriptor sortDescriptorWithKey:@"lesson" ascending:YES];
fetch.sortDescriptors = @[sortGroup];

NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];

NSError* error;
[controller performFetch:&error];
if (error) {
    NSLog(@"Error: %@", error);
    abort();
}

EDIT:

Here is the Storyboard:

Storyboard

UPDATE

Here's my Code:

TableView.m (important Methods)

-(id)init
{
    self = [super init];
    if (self) {
        NSLog(@"%s",__PRETTY_FUNCTION__);
        self.del = [[UIApplication sharedApplication] delegate];
        self.managedObjectContext = self.del.managedObjectContext;

        NSFetchRequest* fetch = [NSFetchRequest fetchRequestWithEntityName:@"Lessons"];

        NSString *theSelectedDay = @"Mi";

        NSPredicate *pred = [NSPredicate predicateWithFormat:@"lessonToDay.day == %@", theSelectedDay];
        fetch.predicate = pred;
        NSSortDescriptor *sortTime = [NSSortDescriptor sortDescriptorWithKey:@"lessonToTime.start" ascending:YES];
        //NSSortDescriptor *sortGroup = [NSSortDescriptor sortDescriptorWithKey:@"lesson" ascending:YES];
        fetch.sortDescriptors = @[sortTime];

        self.controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch
                                                              managedObjectContext:self.managedObjectContext
                                                                sectionNameKeyPath:@"lessonToTime.start"
                                                                         cacheName:nil];
    }
    return self;
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    static NSString *CellIdentifier = @"Cell";


    // Configure the cell...
    //UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }


    Lessons *lesson = [self.controller objectAtIndexPath:indexPath];
    cell.textLabel.text = lesson.lesson;


    return cell;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.controller sections] objectAtIndex:section];
    // This is the first lesson in this section:
    Lessons *lesson = [sectionInfo objects][0];

    //For testing I changed the type of 'start' and 'end' to string
    NSLog(@"start: %@",lesson.lessonToTime.start);
    NSLog(@"end: %@", lesson.lessonToTime.end );

    NSString *title = [NSString stringWithFormat:@"%@-%@",
                       lesson.lessonToTime.start,
                       lesson.lessonToTime.end];
    return title;
}

RESULT: Result

Upvotes: 1

Views: 3063

Answers (2)

Arek Holko
Arek Holko

Reputation: 9006

You can do this with two View Controllers:

  • DaysViewController - here you show all days. When user selects the cell you get the day associated with the cell and pass it to the second View Controller,
  • LessonsViewController - here you use the passed object when building your NSFetchRequest's predicate

UPDATE: my answer isn't correct anymore, because the problem's description have changed.

Upvotes: 1

Martin R
Martin R

Reputation: 539685

First of all you have to add a predicate that only the lessons for the selected day are displayed:

NSPredicate *pred = [NSPredicate predicateWithFormat:@"lessonToDay.day == %@", theSelectedDay];
fetch.predicate = pred;

To group the table view into sections, you have to set the sectionNameKeyPath: parameter of the fetched results controller, for example to @"lessonToTime.start". This would group all lessons with the same start time into one section. (As I understand your comment, lessons with the same start time have also the same end time, so this should be sufficient.) The same key path must be used as first sort descriptor:

NSSortDescriptor *sortTime = [NSSortDescriptor sortDescriptorWithKey:@"lessonToTime.start" ascending:YES];
NSSortDescriptor *sortGroup = [NSSortDescriptor sortDescriptorWithKey:@"lesson" ascending:YES];
fetch.sortDescriptors = @[sortTime, sortGroup];

NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch
            managedObjectContext:self.managedObjectContext
            sectionNameKeyPath:@"lessonToTime.start"
            cacheName:nil];

To display the section header according to your needs, you have to override titleForHeaderInSection::

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.controller sections] objectAtIndex:section];
    // This is the first lesson in this section:
    Lesson *lesson = [sectionInfo objects][0];
    // Now build some title from lesson.lessonToTime.start and lesson.lessonToTime.end:
    NSString *title = ...;
    return title;
}

Upvotes: 2

Related Questions