Источник данных Diffable для ошибки TableView в iOS 13: несогласованные ассоциации для ходов

Я обновляю свой текущий UITableview для diffable источника данных, предоставленного iOS 13 UITableViewDiffableDataSource.

У меня есть массив с настраиваемым объектом (реализующий метод isEqual:). В viewWillAppear я загружаю данные с диска и вызываю заявку на снимок.

-(void)updateTableViewAnimated:(BOOL)animated API_AVAILABLE(ios(13.0)){
    NSDiffableDataSourceSnapshot *snapshot = [[NSDiffableDataSourceSnapshot alloc]init];
    [snapshot appendSectionsWithIdentifiers:@[@"sectionTitle"]];
    [snapshot appendItemsWithIdentifiers:self.playlists];
    [self.diffDataSource applySnapshot:snapshot animatingDifferences:animated];
}

И все загружается. Но когда я пытаюсь удалить элемент из массива и снова вызвать updateTableViewAnimated:, я получаю исключение.

*** Завершение работы приложения из-за необработанного исключения «NSInvalidArgumentException», причина: «Несогласованные ассоциации для перемещений».

Что это значит? Как я могу решить?


person Fabiosoft    schedule 01.08.2019    source источник
comment
вы нашли решение для этого?   -  person swalkner    schedule 15.10.2019


Ответы (2)


Обновленный ответ

Мне посчастливилось получить ответ на ошибку, которую я поднял по этому поводу. Оказывается, у моего объекта модели были неправильные проверки хеширования и равенства.

Мои быстрые структуры соответствовали Hashable, но предоставляли пользовательскую реализацию Equatable, поэтому я сравнивал только свойство ID, чтобы определить равенство. Это означало, что два объекта можно было считать равными, но иметь разные хэши, что сбивает с толку алгоритм сравнения.

Чтобы решить эту проблему, я просто удалил свою собственную реализацию Equatable и использовал синтезированную версию.

В своем вопросе вы указываете, что реализуете isEqual, ObjC, аналог Swift ==, но вы, вероятно, не предоставляете реализацию hash, которая согласуется с вашей реализацией isEqual во всех случаях.


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

Я не знаю, является ли это той же проблемой, что и у вас, но в моем случае это было вызвано вызовом метода applySnapshot из разных очередей.

В сеансе Advanced Data Sources WWDC упоминалось, что applySnapshot должен вызываться исключительно из фоновой очереди ИЛИ из основной очереди, но не из обоих. Расширенные источники данных WWDC 2019 – 32:00

«Расширенные

В моем случае я использую издатель Combine, чтобы реагировать на изменения в моем источнике данных, и этот издатель иногда отправлял значения в основной поток или фоновый поток. Чтобы решить мою проблему, я добавил .receive(on: RunLoop.Main) в цепочку.

В вашем случае, возможно, вы можете обернуть все, что вызывает updateTableViewAnimated:, в вызов dispatch_async, используя очередь, в которой вы хотите, чтобы он работал (будь то основной или фоновый).

person Jasarien    schedule 30.10.2019

Добавляя информативный ответ Jasarien, вы должны иметь в виду, что UICollectionViewDiffableDataSource использует хэш-код для различения элементов в вашем источнике данных.

если ваша модель является структурой, и в вашей модели источника данных есть два элемента, которые имеют одинаковые значения, протокол Hashable создаст для них одно и то же значение hashValue.

также протокол Equatable вернет true! , что смутит UICollectionViewDiffableDataSource

Решения

  • Убедитесь, что ваш источник данных не имеет дубликатов
  • если вы не можете избежать дубликатов и не возражаете против торможения Equatable, вы можете добавить случайное значение в свой источник данных, но это не рекомендуется, поскольку сгенерированные значения могут быть равны при любом совпадении, как указано в документации * низкая вероятность , но это может случиться *

В зависимости от размера и диапазона диапазона некоторые конкретные значения могут быть представлены чаще, чем другие.

person Mostfa Essam    schedule 06.02.2020
comment
Apple действует здесь как тупой. Это нормально иметь одинаковые данные для разных ячеек. Могут быть ситуации, когда tableview будет отображать одни и те же данные в разных ячейках. Если я добавлю случайные числа, то не будет перемещений, а будут вставки и удаления для всех ситуаций изменения данных - person Aznix; 30.03.2021