Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save jonzhan/e821b7c7fbd13f736768 to your computer and use it in GitHub Desktop.
Save jonzhan/e821b7c7fbd13f736768 to your computer and use it in GitHub Desktop.
UICollectionView and NSFetchedResultsControllerDelegate integration in Swift
var fetchedResultsProcessingOperations: [NSBlockOperation] = []
private func addFetchedResultsProcessingBlock(processingBlock:(Void)->Void) {
fetchedResultsProcessingOperations.append(NSBlockOperation(block: processingBlock))
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Insert:
addFetchedResultsProcessingBlock {self.collectionView!.insertItemsAtIndexPaths([newIndexPath!])}
case .Update:
addFetchedResultsProcessingBlock {self.collectionView!.reloadItemsAtIndexPaths([indexPath!])}
case .Move:
addFetchedResultsProcessingBlock {
// If installsStandardGestureForInteractiveMovement is on
// the UICollectionViewController will handle this on its own.
guard !self.installsStandardGestureForInteractiveMovement else {
return
}
self.collectionView!.moveItemAtIndexPath(indexPath!, toIndexPath: newIndexPath!)
}
case .Delete:
addFetchedResultsProcessingBlock {self.collectionView!.deleteItemsAtIndexPaths([indexPath!])}
}
}
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
switch type {
case .Insert:
addFetchedResultsProcessingBlock {self.collectionView!.insertSections(NSIndexSet(index: sectionIndex))}
case .Update:
addFetchedResultsProcessingBlock {self.collectionView!.reloadSections(NSIndexSet(index: sectionIndex))}
case .Delete:
addFetchedResultsProcessingBlock {self.collectionView!.deleteSections(NSIndexSet(index: sectionIndex))}
case .Move:
// Not something I'm worrying about right now.
break
}
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
collectionView!.performBatchUpdates({ () -> Void in
for operation in self.fetchedResultsProcessingOperations {
operation.start()
}
}, completion: { (finished) -> Void in
self.fetchedResultsProcessingOperations.removeAll(keepCapacity: false)
})
}
deinit {
// Cancel all block operations when VC deallocates
for operation in fetchedResultsProcessingOperations {
operation.cancel()
}
fetchedResultsProcessingOperations.removeAll()
}
@magnas35
Copy link

magnas35 commented Dec 7, 2016

I've been using this successfully but am now trying to use CollectionView.scrollToItem after inserting a new item. Where would you suggest implementing this as I get the 'attempt to scroll to invalid index path' when I put the scrollToItem call immediately after the .insert addFetchjedResultsProcessingBlock call?
Thanks.

Actually I may have solved this. I'll test some more.

@LukasCZ
Copy link

LukasCZ commented Mar 9, 2020

Thank you for this, it's working well.

@jonzhan
Copy link
Author

jonzhan commented Mar 13, 2020

Thank you for this, it's working well.

https://gist.github.com/AppsTitude/ce072627c61ea3999b8d did most of the hard work :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment