Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mikeMTOL/a97deb98c6a6601489155dd37a283595 to your computer and use it in GitHub Desktop.
Save mikeMTOL/a97deb98c6a6601489155dd37a283595 to your computer and use it in GitHub Desktop.
This makes any UICollectionViewController able to handle an NSFetchedResultsController
extension UICollectionViewController: NSFetchedResultsControllerDelegate {
private struct AssociatedKeys {
static var operationsArray = "operationsArrayKey"
}
var fetchedResultsProcessingOperations: [NSBlockOperation]? {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.operationsArray) as? [NSBlockOperation]
}
set {
if let newValue = newValue {
objc_setAssociatedObject(
self,
&AssociatedKeys.operationsArray,
newValue as [NSBlockOperation]?,
.OBJC_ASSOCIATION_RETAIN_NONATOMIC
)
}
}
}
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
self.fetchedResultsProcessingOperations?.forEach { $0.start() }
}, completion: { (finished) -> Void in
self.fetchedResultsProcessingOperations?.removeAll(keepCapacity: false)
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment