Я создаю медиа галерею, используя NSFetchedResultsController
и UICollectionView
.Поскольку существует множество проблем с применением обновлений на collectionView с NSFetchedResultsControllerDelegate
, я использую эту реализацию:
public func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
if type == .insert {
blockOperations.append(
BlockOperation(block: { [weak self] in
self?.collectionView.insertSections(IndexSet(integer: sectionIndex))
})
)
} else if type == .update {
blockOperations.append(
BlockOperation(block: { [weak self] in
self?.collectionView.reloadSections(NSIndexSet(index: sectionIndex) as IndexSet)
})
)
} else if type == .delete {
blockOperations.append(
BlockOperation(block: { [weak self] in
self?.collectionView.deleteSections(NSIndexSet(index: sectionIndex) as IndexSet)
})
)
}
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
if type == .insert {
if self.collectionView.numberOfSections > 0 {
guard let newIndexPathSection = newIndexPath?.section else {
return
}
if self.collectionView.numberOfItems(inSection: newIndexPathSection) == 0 {
self.shouldReloadCollectionView = true
} else {
guard let newIndexPath = newIndexPath else {
return
}
self.blockOperations.append(
BlockOperation(block: { [weak self] in
self?.collectionView.insertItems(at: [newIndexPath])
})
)
}
} else {
self.shouldReloadCollectionView = true
}
} else if type == .update {
guard let indexPath = indexPath else {
return
}
self.blockOperations.append(
BlockOperation(block: { [weak self] in
self?.collectionView.reloadItems(at: [indexPath])
})
)
} else if type == .move {
guard let indexPath = indexPath, let newIndexPath = newIndexPath else {
return
}
self.blockOperations.append(
BlockOperation(block: { [weak self] in
self?.collectionView.moveItem(at: indexPath, to: newIndexPath)
})
)
} else if type == .delete {
guard let indexPath = indexPath else {
return
}
if self.collectionView.numberOfItems(inSection: indexPath.section) == 1 {
self.shouldReloadCollectionView = true
} else {
self.blockOperations.append(
BlockOperation(block: { [weak self] in
self?.collectionView.deleteItems(at: [indexPath])
})
)
}
}
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
if shouldReloadCollectionView {
self.collectionView.reloadData()
} else {
self.collectionView.performBatchUpdates({
for operation: BlockOperation in self.blockOperations {
operation.start()
}
}, completion: { _ in
self.blockOperations.removeAll(keepingCapacity: false)
})
}
}
При сохранении большого количества мультимедиа ясно, что с индексами происходит много изменений,Итак, выдается ошибка:
*** Завершение работы приложения из-за необработанного исключения «NSInternalInconsistencyException», причина: «запрос количества элементов в разделе 1, когда в представлении коллекции только 1 разделы»
Я обнаружил, что это произошло при вызове:
collectionView.numberOfItems(inSection: newIndexPathSection)
, когда вызывается controllerDidChangeAnObject
.
Как я могу решить эту ошибку?Спасибо