Как справиться с несогласованным поведением при изменении значения анимированного снимка экрана?

Я начну с объяснения того, как все должно работать:

У меня есть представление коллекции с композиционным макетом и доступным источником данных.

Ячейки представляют задачи, которые пользователь может щелкнуть и установить как выполненные на сегодняшний день, ячейки имеют разный внешний вид в зависимости от того, установлено ли оно как выполненное или нет, и ячейка проверяет CoreData, чтобы узнать, выполнено ли это или нет.

Теперь я попытался реализовать идею о том, что задачи, выполненные за день, идут в нижнюю часть представления, поэтому вверху отображаются только те, которые еще нужно выполнить. Для этого я установил дескриптор сортировки для моего запроса на выборку.

До этого момента все работает, как ожидалось, но я хотел сделать эту ячейку анимированной, поэтому я изменил dataSource.apply(snapshot, animatingDifferences: false) к true

Теперь он анимирован, но ячейки не меняют внешний вид после завершения.

Вот мой метод setupSnapshot ():

func setupSnapshot() {
        snapshot = NSDiffableDataSourceSnapshot<Section, Task>()
        snapshot.appendSections([.main])
        snapshot.appendItems(fetchedResultsController.fetchedObjects ?? [])
        dataSource.apply(snapshot, animatingDifferences: true)   
    }

Посмотрите: animatedDifferences: false(слева) и true(справа)

Подводя итог, моя цель - получить:

1) анимированные ячейки и 2) изменение внешнего вида, когда установлено как готовое. Кажется, что сanimatedDifferences: falseу меня может быть только цель 2 и сanimatedDifferences: trueможет иметь только цель 1

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

Кто-нибудь может указать, чего мне здесь не хватает?

1 ответ

Решение

После дальнейшего расследования и согласно комментариям отсюда:

Как получить доступный снимок из NSFetchResultsController в iOS 13?

есть разница в поведении в apply(snapshot: animatingDifferences:) когда его параметр animatingDifferences имеет разное значение.

Похоже с animatedDifferences: false под капотом происходит reloadData(), чего не происходит с animatingDifferences: true, по крайней мере, согласно этим комментариям и моему опыту.

Поэтому решение для моего кода настраивает setupSnapshot на:

func setupSnapshot(animated: Bool) {
      snapshot = NSDiffableDataSourceSnapshot<Section, Task>()
      snapshot.appendSections([.main])
      snapshot.appendItems(fetchedResultsController.fetchedObjects ?? [])   
      dataSource.apply(snapshot, animatingDifferences: animated) {
         if animated {
            self.collectionView.reloadData()
         }
      }
}