Связь Core-Data NSFetchedResultsController со многими

Вот моя модель данных:  Модель данных

Я заполнил базу данных данными.

Теперь я хочу отобразить это в виде таблицы. Сначала я хочу выбрать день с атрибутом days, а затем получить его уроки. Я хочу отобразить атрибуты end и start в заголовке (-(NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section)

Затем я хочу отобразить данные урока в правом разделе. Как я могу сделать это с помощью NSFetchedResultsController?

Я установил базовый код:

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();
}

РЕДАКТИРОВАТЬ:

Вот раскадровка:

Раскадровка

ОБНОВЛЕНИЕ

Вот мой код:

TableView.m (важные методы)

-(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;
}

РЕЗУЛЬТАТ: Результат


person iCode    schedule 07.10.2013    source источник
comment
Как правило, вы используете параметр sectionNameKeyPath:, чтобы сгруппировать представление таблицы в разделы. Но ваши требования не ясны: что, если урок A - с 9-11, урок B - с 9-10, а урок C - с 10-11? Как их следует сгруппировать и какими должны быть заголовки разделов?   -  person Martin R    schedule 07.10.2013
comment
@MartinR Время указано. Всегда так: 9-10 = ›урок А, урок Б; 10-11 = ›урок C, урок D, урок E, урок F ... Надеюсь, теперь все понятно.   -  person iCode    schedule 07.10.2013
comment
Описывает ли сущность Days один день, например Понедельник или вторник? Меня просто интересует форма множественного числа.   -  person Martin R    schedule 07.10.2013
comment
Это ошибка. Он описывает один день.   -  person iCode    schedule 07.10.2013


Ответы (2)


Прежде всего, вам нужно добавить предикат, чтобы отображались только уроки для выбранного дня:

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

Чтобы сгруппировать представление таблицы в разделы, вы должны установить параметр sectionNameKeyPath: контроллера выбранных результатов, например, на @"lessonToTime.start". Это сгруппирует все уроки с одинаковым временем начала в один раздел. (Насколько я понимаю ваш комментарий, у уроков с одинаковым временем начала также одинаковое время окончания, поэтому этого должно быть достаточно.) Один и тот же ключевой путь должен использоваться в качестве первого дескриптора сортировки:

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];

Чтобы отобразить заголовок раздела в соответствии с вашими потребностями, вы должны переопределить 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;
}
person Martin R    schedule 07.10.2013
comment
Он не работает должным образом. Я разместил свой код в разделе ОБНОВЛЕНИЕ. Что я сделал не так? - person iCode; 07.10.2013
comment
Вы реализовали numberOfSectionsInTableView: и numberOfRowsInSection: совершенно неправильно. Возвращать фиксированное значение 1 не имеет смысла. Документация NSFetchedResultsController содержит пример кода, как правильно реализовать методы источника данных. - Возможно, прочтите учебник, например raywenderlich. ru / 999 /. - person Martin R; 07.10.2013
comment
Я знаю, что фиксированное значение типа 1 неверно. Но для тестирования сделал вот так. Когда я реализую это так в numberOfSectionsInTableView: return self.controller.section.count, у него 0 секций. Значит, синтаксис доступа к урокам неправильный. (с NSFetchedResultsController) - person iCode; 07.10.2013
comment
Есть еще ошибки, например вы не звоните performFetch. И если вам нужно автоматическое обновление табличного представления для вставленных / удаленных / измененных объектов, вы должны установить делегат FRC и реализовать NSFetchedResultsControllerDelegate методы. - Я действительно предлагаю прочитать несколько руководств или изучить рабочий пример кода. - person Martin R; 07.10.2013
comment
Спасибо мельница! Теперь работает. Забыл только метод performFetch. - person iCode; 07.10.2013

Вы можете сделать это с помощью двух контроллеров представления:

  • DaysViewController - здесь ты показываешь все дни. Когда пользователь выбирает ячейку, вы получаете день, связанный с ячейкой, и передаете его второму контроллеру представления,
  • LessonsViewController - здесь вы используете переданный объект при создании вашего NSFetchRequest's predicate

ОБНОВЛЕНИЕ: мой ответ больше не правильный, потому что описание проблемы изменилось.

person Arek Holko    schedule 07.10.2013
comment
СПАСИБО за ваш ответ. Отредактировал свой вопрос, добавил Раскадровку. Вверху пользователь может выбрать день. - person iCode; 07.10.2013