Как избежать отмены выбора всех элементов uicollectionview при применении нового снимка?

Когда я вызываю dataSource?.apply(snapshot, animatingDifferences: true), соответствующий UICollectionView отменяет выбор всех ячеек.

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

Как избежать отмены выбора всех элементов коллекции при вызове apply(snapshot: animatingDifferences)?


person AirXygène    schedule 04.05.2021    source источник
comment
Очевидно, многое зависит от того, что вы делаете, чтобы показать выбор пользователю.   -  person matt    schedule 04.05.2021
comment
@matt — фон ячейки рисуется другим цветом. На самом деле я использую UIBackgroundConfiguration, но не думаю, что это актуально. Перед применением (снимок:) выбор UICollectionView не пуст, после вызова он есть.   -  person AirXygène    schedule 04.05.2021
comment
Конечно актуально. Здесь нужно подумать про себя, что понятие выбора правильно основано на данных, а не на строках. Вы каким-то образом настроили код, который окрашивает фон. Этот код должен осознавать, являются ли эти данные выбранными данными.   -  person matt    schedule 04.05.2021
comment
Я взял некоторое время, чтобы подумать об этом, но я думаю, что буду придерживаться другого мнения. Информация о выборе не должна быть частью модели. Я мог бы согласиться с тем, что это где-то между моделью и представлением, но это создает проблему синхронизации этой информации со списком выбранных путей индекса, хранящихся внутри представления коллекции. Я нашел основную причину проблемы (см. ответ), и она не связана. В любом случае, я благодарю вас за вашу попытку помочь. С наилучшими пожеланиями.   -  person AirXygène    schedule 10.05.2021


Ответы (1)


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

Когда применяется моментальный снимок, поведение UICollectionViewDiffableDataSource отличается, независимо от того, является ли ItemIdentifierType типом значения или ссылочным типом.

Конечно, ваш ItemIdentifierType должен соответствовать Hashable, но при вызове apply(snapshot, animatingDifferences: true):

  • Если ItemIdentifierType является типом-значением (структурой), то вызываются его функции == и hash, чтобы сравнить элементы только что полученного снимка с элементами отображаемого в данный момент снимка, что позволяет найти различия, анимировать различия, и сохраните выбор, если он есть (это была исходная проблема, о которой я попросил помощи).
  • Если ItemIdentifierType является ссылочным типом (классом), то его функции == и hash не вызываются, что означает, что элементы нового снимка и отображаемого в данный момент снимка сравниваются с голым ссылочным равенством (являются указатели равны). Как следствие, если вы создали свои элементы с нуля с новыми экземплярами, имеющими тот же хэш, то сравнение всегда будет ложным, и вы не получите анимацию, и вы потеряете выбор.

Одним из простых обходных путей в этой ситуации является инкапсуляция вашего ссылочного типа в структуру, которая будет пересылать == и hash классовым, и использовать эту структуру как ItemIdentifierType.

person AirXygène    schedule 10.05.2021