Изменение пользовательских данных UICollectionView
В моем проекте я использую UICollectionView для отображения сетки значков.
Пользователь может изменить порядок, щелкнув сегментированный элемент управления, который вызывает выборку из основных данных с помощью другого NSSortDescriptor.
Объем данных всегда один и тот же, только заканчиваясь в разных разделах/строках:
- (IBAction)sortSegmentedControlChanged:(id)sender {
_fetchedResultsController = nil;
_fetchedResultsController = [self newFetchResultsControllerForSort];
NSError *error;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
[self.collectionView reloadData];
}
Проблема в том, что reloadData не оживляет изменения, UICollectionView просто появляется с новыми данными.
Должен ли я отслеживать, в какой ячейке indexPath была до и после изменения, и использовать [self.collectionView moveItemAtIndexPath: toIndexPath:] для выполнения анимации для изменения или есть лучший метод?
Я не получил много в subclassing collectionViews, поэтому любая помощь будет большой...
Спасибо,
Билл.
Ответы
Ответ 1
reloadData не анимирует, и не делает это с надежностью, когда помещается в блок анимации UIView. Он хочет быть в блоке выполнения UICollecitonView performBatchUpdates, поэтому попробуйте что-то более похожее:
[self.collectionView performBatchUpdates:^{
[self.collectionView reloadData];
} completion:^(BOOL finished) {}];
Ответ 2
Обтекание -reloadData
в -performBatchUpdates:
, похоже, не вызывает односекторный просмотр коллекции для анимации.
[self.collectionView performBatchUpdates:^{
[self.collectionView reloadData];
} completion:nil];
Однако этот код работает:
[self.collectionView performBatchUpdates:^{
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
} completion:nil];
Ответ 3
Это то, что я сделал, чтобы оживить перезагрузку ВСЕХ СЕКЦИЙ:
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.collectionView.numberOfSections)]];
Swift 3
let range = Range(uncheckedBounds: (0, collectionView.numberOfSections))
let indexSet = IndexSet(integersIn: range)
collectionView.reloadSections(indexSet)
Ответ 4
Перезагрузка всего представления коллекции внутри блока performBatchUpdates:completion:
делает сбойную анимацию для меня на симуляторе iOS 9. Если у вас есть определенный UICollectionViewCell
, который вы хотите удалить, или если у вас есть путь к нему, вы можете вызвать deleteItemsAtIndexPaths:
в этом блоке. Используя deleteItemsAtIndexPaths:
, он выполняет плавную и приятную анимацию.
UICollectionViewCell* cellToDelete = /* ... */;
NSIndexPath* indexPathToDelete = /* ... */;
[self.collectionView performBatchUpdates:^{
[self.collectionView deleteItemsAtIndexPaths:@[[self.collectionView indexPathForCell:cell]]];
// or...
[self.collectionView deleteItemsAtIndexPaths:@[indexPath]];
} completion:nil];
Ответ 5
В тексте справки говорится:
Вызовите этот метод, чтобы перезагрузить все элементы в виде коллекции. Это приводит к тому, что просмотр коллекции отменяет любые видимые в данный момент элементы и перерисовать их. Для эффективности отображается только просмотр коллекции. эти ячейки и дополнительные виды, которые видны. Если данные сбора сжимаются в результате перезагрузки, просмотр коллекции соответственно корректирует смещения прокрутки. Вы не должны называть это метод в середине блоков анимации, где элементы вставлен или удален. Вставки и удаления автоматически вызывают табличные данные должны быть соответствующим образом обновлены.
Я думаю, что ключевая часть - "вызывает просмотр коллекции, чтобы удалить любые видимые в данный момент элементы". Как это будет оживлять движение предметов, которые оно отбросило?
Ответ 6
Если вы хотите больше контроля и настраиваемой функции, отметьте this,
он содержит очень подробное объяснение различных способов анимации UICollectionViewCell.
Ответ 7
Для быстрых пользователей это удобно -
collectionView.performBatchUpdates({
self.collectionView.reloadSections(NSIndexSet(index: index))
}, completion: nil)