Создание разделов с помощью NSFetchedResultsController, на лету

Я использую NSFetchedResultsController (NSFRC) для отображения информации в UITableView. Я пытаюсь создать для пользователя возможность сортировать ячейки в разделах, а не в алфавитном порядке. Проблема в том, что секция будет определяться с помощью загруженной информации. Кроме того, раздел для каждого элемента будет меняться относительно часто, поэтому я не хочу сохранять этот раздел. Я заметил упоминание о переходных атрибутах в своих исследованиях аналогичных проблем, но я никогда не использовал их, прежде чем я не уверен, могу ли я использовать их, имея в виду, что все вычисления выполняются после того, как данные уже загружены, и я также хочу, чтобы это решение было совместимо с предыдущим Core Data database. Также я не особенно хорош в Core Data, (и Objective-C при этом!), Поэтому я не совсем уверен, как бы я это сделал.

Итак, вот что я хочу использовать, если мы используем переходные атрибуты (этот следующий бит теоретический, поскольку я не знаю, являются ли переходные атрибуты правильными способами продвижения вперед). Мне хотелось бы 4 возможных раздела, 0-3 (я переименую их с помощью TableView delegate, чтобы обойти проблемы сортировки). Когда вычисления будут выполнены, каждой ячейке будет назначен переходный атрибут (при необходимости раздел по умолчанию будет равен 2). Я надеюсь, что все это имеет смысл.

Верно, теперь для некоторого теоретического кода. Сначала я создаю свойство переходного процесса в окне модели данных и делаю его переходным процессом, установив флажок переходного процесса... Звучит достаточно просто.

В коде для вычислений в willDisplayCell (это необходимо сделать в wDC по нескольким причинам), объект можно сохранить следующим образом:

MyEntity *myEntity = [self.fetchedResultsController objectAtIndexPath:indexPath];

myEntity.sectionTransientProperty = 2;

if (![self.managedObjectContext save:&error]) {
    NSLog(@"Error: %@", error);
    FATAL_CORE_DATA_ERROR(error);
    return;
}  

Готово, да? Это то, как мы присваиваем значение переходному свойству?

Затем я изменяю параметр сортировки в NSFRC, когда я его выделяю:

fetchedResultsController = [[NSFetchedResultsController alloc]
                                initWithFetchRequest:fetchRequest
                                managedObjectContext:self.managedObjectContext
                                sectionNameKeyPath:@"sectionTransientProperty"
                                cacheName:@"MyEntity"];

Как мы это делаем, что еще мне нужно делать? Или у меня это так ужасно неправильно, я должен просто отказаться от Core Data and NSFRC? Если бы вы, ребята, могли помочь мне в этом, я бы очень признателен. Если вам нужно, чтобы я опубликовал больше кода, я был бы рад.

С уважением,
Mike

Ответ 1

Если вы хотите FRC с разделами, вам нужно добавить дескриптор сортировки в запрос выборки, и этот дескриптор сортировки не может быть основан на переходных атрибутах.

Смотрите документацию initWithFetchRequest: managedObjectContext: sectionNameKeyPath: cacheName:`:

Если контроллер генерирует разделы, первый дескриптор сортировки в массив используется для группировки объектов в разделы; его ключ должен либо быть таким же, как sectionNameKeyPath или относительное упорядочение использование его ключа должно совпадать с использованием sectionNameKeyPath.

и Извлечь предикаты и сортировать дескрипторы в "Руководстве по программированию основных данных":

SQL-хранилище, с другой стороны, компилирует предикат и сортирует дескрипторы для SQL и оценивает результат в самой базе данных. Это делается в первую очередь для производительности, но это означает, что оценка происходит в среде не Cocoa и поэтому сортирует дескрипторы (или предикаты), которые полагаются на Cocoa, не могут работать. Поддерживаемый сорт селекторы... Кроме того, вы не можете сортировать по свойствам переходных процессов, используя хранилище SQLite.

Это означает, что вы не можете создавать разделы исключительно по переходным атрибутам. Вам нужен постоянный атрибут, который создает упорядочение для разделов.

ОБНОВЛЕНИЕ: типичным использованием переходного атрибута как sectionNameKeyPath является: у ваших объектов есть атрибут "timeStamp" , и вы хотите сгруппировать объекты в разделы с одной секцией в месяц (см. DateSectionTitles пример кода из библиотеки разработчиков iOS). В этом случае у вас есть

  • постоянный атрибут "TimeStamp",
  • используйте "timeStamp" в качестве первого дескриптора сортировки для запроса выборки,
  • переходный атрибут "sectionIdentifier" , который используется как sectionNameKeyPath. "sectionIdentifier" вычисляется из "timeStamp" и возвращает строку, представляющую год и месяц метки времени, например. "2013-01".

Первое, что делает FRC, - сортировать все выбранные объекты в соответствии с атрибутом "TimeStamp". Затем объекты сгруппированы по разделам в соответствии с атрибутом "sectionIdentifier" .

Итак, для FRC для группировки объектов в разделы вам действительно нужен постоянный атрибут. Самое простое решение - добавить постоянный атрибут "sectionNumber" к вашей сущности и использовать его для "sectionNameKeyPath" и для первого дескриптора сортировки.