Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save AppsTitude/ce072627c61ea3999b8d to your computer and use it in GitHub Desktop.
Save AppsTitude/ce072627c61ea3999b8d to your computer and use it in GitHub Desktop.
UICollectionView and NSFetchedResultsControllerDelegate integration in Swift
// I just implemented that with Swift. So I would like to share my implementation.
// First initialise an array of NSBlockOperations:
var blockOperations: [NSBlockOperation] = []
// In the did change object method:
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
if type == NSFetchedResultsChangeType.Insert {
println("Insert Object: \(newIndexPath)")
blockOperations.append(
NSBlockOperation(block: { [weak self] in
if let this = self {
this.collectionView!.insertItemsAtIndexPaths([newIndexPath!])
}
})
)
}
else if type == NSFetchedResultsChangeType.Update {
println("Update Object: \(indexPath)")
blockOperations.append(
NSBlockOperation(block: { [weak self] in
if let this = self {
this.collectionView!.reloadItemsAtIndexPaths([indexPath!])
}
})
)
}
else if type == NSFetchedResultsChangeType.Move {
println("Move Object: \(indexPath)")
blockOperations.append(
NSBlockOperation(block: { [weak self] in
if let this = self {
this.collectionView!.moveItemAtIndexPath(indexPath!, toIndexPath: newIndexPath!)
}
})
)
}
else if type == NSFetchedResultsChangeType.Delete {
println("Delete Object: \(indexPath)")
blockOperations.append(
NSBlockOperation(block: { [weak self] in
if let this = self {
this.collectionView!.deleteItemsAtIndexPaths([indexPath!])
}
})
)
}
}
// In the did change section method:
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
if type == NSFetchedResultsChangeType.Insert {
println("Insert Section: \(sectionIndex)")
blockOperations.append(
NSBlockOperation(block: { [weak self] in
if let this = self {
this.collectionView!.insertSections(NSIndexSet(index: sectionIndex))
}
})
)
}
else if type == NSFetchedResultsChangeType.Update {
println("Update Section: \(sectionIndex)")
blockOperations.append(
NSBlockOperation(block: { [weak self] in
if let this = self {
this.collectionView!.reloadSections(NSIndexSet(index: sectionIndex))
}
})
)
}
else if type == NSFetchedResultsChangeType.Delete {
println("Delete Section: \(sectionIndex)")
blockOperations.append(
NSBlockOperation(block: { [weak self] in
if let this = self {
this.collectionView!.deleteSections(NSIndexSet(index: sectionIndex))
}
})
)
}
}
// And finally, in the did controller did change content method:
func controllerDidChangeContent(controller: NSFetchedResultsController) {
collectionView!.performBatchUpdates({ () -> Void in
for operation: NSBlockOperation in self.blockOperations {
operation.start()
}
}, completion: { (finished) -> Void in
self.blockOperations.removeAll(keepCapacity: false)
})
}
// I personally added some code in the deinit method as well, in order to cancel the operations when the ViewController is about to get deallocated:
deinit {
// Cancel all block operations when VC deallocates
for operation: NSBlockOperation in blockOperations {
operation.cancel()
}
blockOperations.removeAll(keepCapacity: false)
}
@razor28
Copy link

razor28 commented Jul 2, 2015

Thank you! It works like a charm.

@jonzhan
Copy link

jonzhan commented Nov 5, 2015

Thank you for sharing. I made fork at https://gist.github.com/jonzhan/e821b7c7fbd13f736768 that is a little more compact and supports installsStandardGestureForInteractiveMovement on UICollectionViewController in case anybody else wants that!

@RonGafni
Copy link

RonGafni commented Aug 7, 2016

Thank you! amazing!

@nor0x
Copy link

nor0x commented Oct 13, 2016

Thank you for sharing. I'm using Swift 3 and Xcode 8.0 to build a UICollectionView with NSFetchedResultsController integration, this Gist was working fine for me on older versions of Swift an iOS, however on iOS 10 i receive the following error message, which gets called in controllerDidChangeContent.

This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread.

Has anybody upgraded to the latest version of Swift and Xcode and has a working version of UICollectionView + NSFetchedResultsController?

@nazywamsiepawel
Copy link

hey all, just converted the above to swift 3 : https://gist.github.com/nazywamsiepawel/e88790a1af1935ff5791c9fe2ea19675

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