NSFetchedResultsContollerDelegate for CollectionView
Combining a fetched results controller with a collection view is a bit tricky.
The problem is explained in
- http://ashfurrow.com/blog/how-to-use-nsfetchedresultscontroller-with-uicollectionview
If you're looking for how to get around the
NSInternalInconsistencyException
runtime exception with
UICollectionView
, I have an example on GitHub detailing how to queue
updates from the NSFetchedResultsControllerDelegate.The problem is that the existing
UITableView
class usesbeginUpdates
andendUpdates
to submit batches to the table view.UICollectionView
has a newperformBatchUpdates:
method, which takes a block parameter
to update the collection view. That's sexy, but it doesn't work well
with the existing paradigm for NSFetchedResultsController.
Fortunately, that article also provides a sample implementation:
- https://github.com/AshFurrow/UICollectionView-NSFetchedResultsController
From the README:
This is an example of how to use the new
UICollectionView
with
NSFetchedResultsController
. The trick is to queue the updates made
through theNSFetchedResultsControllerDelegate
until the controller
finishes its updates.UICollectionView
doesn't have the same
beginUpdates
andendUpdates
thatUITableView
has to let it work easily
withNSFetchedResultsController
, so you have to queue them or you get
internal consistency runtime exceptions.
NSFetchedResultsContollerDelegate for CollectionView
Combining a fetched results controller with a collection view is a bit tricky.
The problem is explained in
- http://ashfurrow.com/blog/how-to-use-nsfetchedresultscontroller-with-uicollectionview
If you're looking for how to get around the
NSInternalInconsistencyException
runtime exception with
UICollectionView
, I have an example on GitHub detailing how to queue
updates from the NSFetchedResultsControllerDelegate.The problem is that the existing
UITableView
class usesbeginUpdates
andendUpdates
to submit batches to the table view.UICollectionView
has a newperformBatchUpdates:
method, which takes a block parameter
to update the collection view. That's sexy, but it doesn't work well
with the existing paradigm for NSFetchedResultsController.
Fortunately, that article also provides a sample implementation:
- https://github.com/AshFurrow/UICollectionView-NSFetchedResultsController
From the README:
This is an example of how to use the new
UICollectionView
with
NSFetchedResultsController
. The trick is to queue the updates made
through theNSFetchedResultsControllerDelegate
until the controller
finishes its updates.UICollectionView
doesn't have the same
beginUpdates
andendUpdates
thatUITableView
has to let it work easily
withNSFetchedResultsController
, so you have to queue them or you get
internal consistency runtime exceptions.
collectionView, didSelectItemAtIndexPath some issue
you have to set identifier for viewcontroller and call the method like
CallViewController *vc=[self.storyboard instantiateViewControllerWithIdentifier:@"CallViewController"];
[self.navigationController pushViewController:vc animated:YES];
and be sure you had embedded Navigation View Controller.
Delete multiple Core Data objects: Issue with NSFetchedResultsController
If you delete several images, and then save the context, the FRC processes all the deletions - so its sections
, fetchedObjects
, etc, reflect all those changes. But it then calls the didChangeObject:
delegate method separately for each change. In that method, you call the collectionView update methods (eg. deleteItems
); the collectionView then calls its dataSource methods and does a quick tally up: there were X items, Y items were deleted, there are now Z items and throws an error because Z != X-Y.
When a FRC is used with a tableView, this problem is overcome by using the tableView beginUpdates
and endUpdates
calls in the FRC controllerWillChangeContent:
and controllerDidChangeContent:
delegate methods. This causes the tableView to defer doing the tally up until ALL the individual changes have been processed - at which point the numbers do add up.
Your solution - to call saveContext
after each deletion - causes the FRC to process each deletion in turn: updating its sections
, fetchedObjects
, etc, to reflect only one deletion at a time. This keeps the FRC's data in sync with the collectionView. One possible refinement would be to call processPendingChanges
on the context after each deletion, instead of saving the context. This avoids saving data when you might not want to, but nonetheless causes each deletion to be processed separately.
The alternative is to mimic the tableView's beginUpdates/endUpdates mechanism for holding all the collectionView updates until all the FRC updates have been processed. This works broadly as follows:
- Create arrays to keep track of the changes (inserts, deletes).
- Each time
didChangeObject:
is called, add the corresponding indexPath to the relevant array. - When
controllerDidChangeContent:
is called, iterate through the arrays (deletions first, when inserts) calling the corresponding collectionView update methods. (Then empty the arrays ready for the next batch of updates).
Some good explanations and potential implementations are included in this question and its answers.
UICollectionViewController halts scrolling when inserting new cells
It turns out I had a UIRefreshControl object that was calling endRefreshing()
when I downloaded new data. This apparently halts scrolling.
Related Topics
How to Detect a 'Click' Gesture in Swiftui Tvos
How to Get Date and Time to Show a Clock in Uilabel
Open a Viewcontroller from Remote Notification
Reading an Inputstream into a Data Object
Uitableview - Multiple Selection and Single Selection
Simple Clickable Link in Cocoa and Swift
Delete All Characters After a Certain Character from a String in Swift
How to Compile Latest Swift Version on Older Xcode
Swift - How to Create a View with a Shape Cropped in It
Swift 4 - Notification Center Addobserver Issue
iOS Tabbar Item Title Issue in iOS13
How to Animate Transition Between Views in Swiftui
Show Folder's Contents in Finder Using Swift
How to Make a Https Request to a Server in Swift
How to Hide the Navigationbar When Embedding Swiftui in Uikit
Swift: Popover Dismiss Callback
Subclass of Gkgraphnode Costtonode Method Never Getting Called