Контекст - это все, что касается Core Data. Никакой каламбур.

Примечание: этот пост предполагает некоторые базовые знания Core Data.

Что вы получаете, когда используете NSFetchedResultsController с Core Data? Вы можете быть уверены в том, что вставки, удаления и перезагрузки ячеек таблицы выполняются плавно, пассивно и безболезненно. Безболезненно, если вы не попытаетесь сделать что-то столь же простое, как обновление связанного объекта и ожидать, что это отразится в пользовательском интерфейсе.

Предварительное условие

Документы Apple утешают, что все будет автоматизировано за вас.

Когда вам нужно изменить отношение, Core Data позаботится о поддержании согласованности графа объектов за вас, поэтому вам нужно изменить только один конец отношения. Эта функция применяется к отношениям «к одному», «ко многим» и «многие ко многим».

Когда я обновляю отношения, их другой конец также отражает эти изменения. Звучит хорошо, правда?

Это хорошо. Я обновил Один в моих отношениях Один-ко-многим, и некоторые Отладка пещерного человека показывают, что Множество отражают это изменение. Согласно документации NSFetchedResultsController все должно работать автоматически.

После инициализации полученного контроллера результатов вы назначаете ему делегата. Делегат уведомит контроллер табличного представления о любых изменениях в базовой структуре данных.

Но так бывает не всегда. Фактически, когда я изменил некоторые данные об отношениях, мой NSFetchedResultsController вообще не обновился.

Мой предикат для контроллера должен был проверить, были ли видимы как элемент, на котором я основывал свои ячейки табличного представления, так и его групповой объект (который был основой для разделов табличного представления). Теоретически, скрытие группы скрывает все элементы в группе без необходимости перебирать их и настраивать их видимость индивидуально.

NSPredicate(format: "visible = YES && group.visible = YES")

Но всякий раз, когда я менял видимость группы, ничего не происходило. Я мог удалить всю группу, и правило каскада удаления вступило в силу, и все элементы исчезли из представления таблицы, как и было сказано в документации. Я мог изменять данные об элементе, и он обновлял метки в табличном представлении - точно так, как Apple сказала мне, что это будет. Я мог бы скрыть отдельные элементы, и это обновило бы представление таблицы - именно так, как вы этого ожидали.

Так почему же настройка видимости объекта моей группы не была отражена в контроллере полученных результатов?

Постусловие

Мне потребовалась целая вечность, чтобы найти решение. Наконец, кто-то из Stack Overflow объяснил, что происходит:

Я позволю вам судить, является ли это ошибкой в ​​FRC или нет ... Причина в том, что объект, отслеживаемый FRC, не изменился. Да, путь ключа предиката изменился, но FRC содержит фактически измененные сущности [Item] и [Group].

Внезапно все обрело смысл. Мне пришлось обновить ключевой путь отношения для ссылки на группу моего элемента после обновления группы. Я совершенно забыл о ключевых путях. Удовольствие от дизайна Obj-C при кодировании на Swift. Эта глупо выглядящая строка кода - вот что наконец заставило его работать:

item.group.visible = item.group.visible

Ух ты. Будет интересно объяснить это в следующем обзоре кода! 😂
Итак, помните, что при использовании извлеченного контроллера результатов Core Data не заботится о поддержании согласованности графа объектов за вас. Вам действительно необходимо изменить оба конца отношений. Возможно, после Swift 3.0 Apple обновит Core Data, сделав его более Swifty, как это сделала Realm.

Между прочим, если вы работаете с NSFetchedResultsController, вам определенно стоит сэкономить время и почитать этот пост Майкла Гаше о решении некоторых проблем с NSFetchedResultsController. У него есть несколько действительно полезных советов и наблюдений по работе с контекстами фона и переднего плана при использовании FRC.