Изменение пользовательских данных 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)