Ответ 1
Чтобы получить размер содержимого после перезагрузки, попробуйте вызвать collectionViewContentSize
объекта макета. Меня устраивает.
Кто-нибудь знает, почему contentSize не обновляется сразу после вызова reloadData в UICollectionView?
Если вам нужно знать contentSize, лучшая работа, которую я нашел, это следующее:
[_collectionView reloadData];
double delayInSeconds = 0.0001;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(DISPATCH_TIME_NOW, dispatch_get_main_queue(), ^(void)
{
// TODO: Whatever it is you want to do now that you know the contentSize.
});
Очевидно, что это довольно хрупкий взлом, который делает предположения о внедрении Apple, но до сих пор он оказался достаточно надежным.
Есть ли у кого-нибудь другие способы обхода или знания о том, почему это происходит? Я обсуждаю отправку радара, потому что я не могу понять, почему они не могут вычислить contentSize в том же цикле запуска. Вот как UITableView работал для всей своей реализации.
EDIT: этот вопрос используется для ссылки на метод setContentOffset внутри блока, потому что я хочу прокрутить представление коллекции в моем приложении. Я удалил вызов метода, потому что ответы людей были сосредоточены на том, почему я не использовал scrollToItemAtIndexPath внутри того, почему contentSize не обновляется.
Чтобы получить размер содержимого после перезагрузки, попробуйте вызвать collectionViewContentSize
объекта макета. Меня устраивает.
Это сработало для меня:
[self.collectionView.collectionViewLayout invalidateLayout];
[self.collectionView.collectionViewLayout prepareLayout];
Изменить: я только что протестировал это, и действительно, когда данные изменятся, мое первоначальное решение выйдет из строя со следующим:
"Недопустимое обновление: недопустимое количество элементов в разделе 0. Количество элементов, содержащихся в существующем разделе после обновления (7), должно быть равно количеству элементов, содержащихся в этом разделе, перед обновлением (100), плюс или минус количество элементов, вставленных или удаленных из этого раздела (0 вставлено, 0 удалено) и плюс или минус количество элементов, перемещенных в или из этого раздела (0 перемещен, 0 перемещен).
Правильный способ справиться с этим состоит в том, чтобы вычислять вставки, удаления и перемещения всякий раз, когда источник данных изменяется, и использовать при выполнении команды executeBatchUpdates. Например, если в конец массива, являющегося источником данных, добавлены два элемента, это будет код:
NSArray *indexPaths = @[indexPath1, indexPath2];
[self.collectionView performBatchUpdates:^()
{
[self.collectionView insertItemsAtIndexPaths:indexPaths];
} completion:^(BOOL finished) {
// TODO: Whatever it is you want to do now that you know the contentSize.
}];
Ниже представлено отредактированное решение моего первоначального ответа Kernix, которое, как я думаю, не гарантируется.
Попробуйте выполнитьBatchUpdates: завершение: в UICollectionView. У вас должен быть доступ к обновленным свойствам в блоке завершения. Это будет выглядеть так:
[self.collectionView reloadData];
[self.collectionView performBatchUpdates:^()
{
} completion:^(BOOL finished) {
// TODO: Whatever it is you want to do now that you know the contentSize.
}];
Сначала вызовите prepareLayout, а затем вы получите правильный контент. Размер:
[self.collectionView.collectionViewLayout prepareLayout];