Перезагрузка UICollectionView с использованием метода reloadData возвращается непосредственно перед перезагрузкой данных

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

Я пробовал код, такой как

[self.collectionView reloadData];
[self configure cells]; // BOOM! cells are nil

Я также пытался использовать

[self.collectionView performBatchUpdates:^{
  [self.collectionView reloadData];
    } completion:^(BOOL finished) {
        // notify that completed and do the configuration now
  }];

но когда я перезагружаю данные, я получаю сбои.

Как я могу перезагрузить данные в коллекцию, и только когда она закончила перезагрузку - сделать конкретный обработчик завершения


person Avner Barr    schedule 14.08.2013    source источник
comment
Я думаю, что столкнулся с подобной проблемой. Проблема в том, что ячейки загружаются во время layoutSubview, что происходит во время следующего прохода цикла выполнения. К сожалению, я пока не нашел решения. Интересно, почему у UICollectionViewDelegate нет таких методов, как: - collectionView:willBeginDisplayingCell:forItemAtIndexPath: а есть: - collectionView:didEndDisplayingCell:forItemAtIndexPath: Вы уже решили этот вопрос?   -  person lukewar    schedule 20.08.2013
comment
Что происходит, так это то, что блок пакетных обновлений ожидает, что вы сделаете вызовы для добавления и удаления строк/разделов, которые соответствуют новому количеству строк и разделов, которое происходит во время перезагрузки. Если этого не происходит, выдается утверждение.   -  person Scott Ahten    schedule 04.01.2015


Ответы (3)


Это вызвано тем, что ячейки добавляются во время layoutSubviews, а не в reloadData. Поскольку layoutSubviews выполняется во время следующего прохода цикла выполнения после reloadData, ваши ячейки пусты. Попробуйте сделать это:

[self.collectionView reloadData];
[self.collectionView layoutIfNeeded];
[self configure cells]; 

У меня была аналогичная проблема, и я решил ее таким образом.

person lukewar    schedule 21.08.2013
comment
У меня была именно эта проблема, когда visibleCells было 0 после вызова -reloadData. Вызов -layoutIfNeeded исправил это. Люквар ответ должен быть принят. - person Paulo Fierro; 27.06.2014
comment
Я хотел бы добавить, что это решение чрезвычайно полезно для принудительной синхронной перезагрузки представления коллекции, если вы делаете асинхронные обновления из основных данных, что устраняет огромные головные боли и сбои. - person Mazyod; 01.06.2015
comment
Вы должны вызвать setNeedsLayout, а затем layoutIfNeeded, если хотите гарантировать цикл компоновки. - person TheCodingArt; 01.02.2017

Если вы хотите выполнить некоторый код после того, как ваш collectionView завершил метод reloadData(), попробуйте это (Swift):

    self.collectionView.reloadData()
    self.collectionView.layoutIfNeeded()
    dispatch_async(dispatch_get_main_queue()) { () -> Void in
        // Put the code you want to execute when reloadData is complete in here
    }

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

person Alan Scarpa    schedule 01.02.2016
comment
ну, это не совсем так, блок отправки может быть вставлен между некоторыми операциями основного потока, см. stackoverflow.com/a/10450867/4003774 . Но ваш код будет работать (даже без dispatch_async) благодаря layoutIfNeeded (см. ответ @lukewar) - person Matej Vargovčík; 14.03.2017

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

[collectionView deleteItemsAtIndexPaths:indexesToDelete];
[collectionView insertSections:sectionsToInsert];
[collectionView reloadItemsAtIndexPaths:fooPaths];

внутри блока performBatchUpdates:. Этот метод reloadData можно использовать только для грубого обновления, когда все элементы удаляются и снова выкладываются без анимации.

person kelin    schedule 04.06.2015
comment
У меня была гонка между запросом на обновление и ответом API, и это помогло. Я просто удаляю и вставляю разделы, которые хочу перезагрузить, вместо reloadData: self.collectionView?.performBatchUpdates({ self.collectionView?.deleteSections(IndexSet(arrayLiteral: 0)) self.collectionView?.insertSections(IndexSet(arrayLiteral: 0)) }, completion: nil) - person Aleksander Niedziolko; 21.06.2017