Skip to content

Instantly share code, notes, and snippets.

@catlan
Forked from MrRooni/gist:4988922
Last active March 31, 2018 10:20
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save catlan/01eb0f83554e44335c2a to your computer and use it in GitHub Desktop.
Save catlan/01eb0f83554e44335c2a to your computer and use it in GitHub Desktop.
@interface SomeViewController ()
// Declare some collection properties to hold the various updates we might get from the NSFetchedResultsControllerDelegate
@property (nonatomic, strong) NSMutableIndexSet *deletedSectionIndexes;
@property (nonatomic, strong) NSMutableIndexSet *insertedSectionIndexes;
@property (nonatomic, strong) NSMutableArray *deletedRowIndexPaths;
@property (nonatomic, strong) NSMutableArray *insertedRowIndexPaths;
@property (nonatomic, strong) NSMutableArray *updatedRowIndexPaths;
@end
@implementation SomeViewController
#pragma mark - NSFetchedResultsControllerDelegate methods
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
if (type == NSFetchedResultsChangeInsert) {
if ([self.insertedSectionIndexes containsIndex:newIndexPath.section]) {
// If we've already been told that we're adding a section for this inserted row we skip it since it will handled by the section insertion.
return;
}
[self.insertedRowIndexPaths addObject:newIndexPath];
} else if (type == NSFetchedResultsChangeDelete) {
if ([self.deletedSectionIndexes containsIndex:indexPath.section]) {
// If we've already been told that we're deleting a section for this deleted row we skip it since it will handled by the section deletion.
return;
}
[self.deletedRowIndexPaths addObject:indexPath];
} else if (type == NSFetchedResultsChangeMove) {
if ([self.insertedSectionIndexes containsIndex:newIndexPath.section] == NO) {
[self.insertedRowIndexPaths addObject:newIndexPath];
}
if ([self.deletedSectionIndexes containsIndex:indexPath.section] == NO) {
[self.deletedRowIndexPaths addObject:indexPath];
}
} else if (type == NSFetchedResultsChangeUpdate) {
[self.updatedRowIndexPaths addObject:indexPath];
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type
{
switch (type) {
case NSFetchedResultsChangeInsert:
[self.insertedSectionIndexes addIndex:sectionIndex];
break;
case NSFetchedResultsChangeDelete: {
[self.deletedSectionIndexes addIndex:sectionIndex];
NSMutableArray *indexPathsInSection = [NSMutableArray array];
for(NSIndexPath *indexPath in self.deletedRowIndexPaths)
{
if (indexPath.section == sectionIndex)
{
[indexPathsInSection addObject:indexPath];
}
}
[self.deletedRowIndexPaths removeObjectsInArray:indexPathsInSection];
break;
}
default:
; // Shouldn't have a default
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
NSInteger totalChanges = [self.deletedSectionIndexes count] +
[self.insertedSectionIndexes count] +
[self.deletedRowIndexPaths count] +
[self.insertedRowIndexPaths count] +
[self.updatedRowIndexPaths count];
if (totalChanges > 50)
{
[self.tableView reloadData];
}
else
{
[self.tableView beginUpdates];
[self.tableView deleteSections:self.deletedSectionIndexes withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView insertSections:self.insertedSectionIndexes withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView deleteRowsAtIndexPaths:self.deletedRowIndexPaths withRowAnimation:UITableViewRowAnimationLeft];
[self.tableView insertRowsAtIndexPaths:self.insertedRowIndexPaths withRowAnimation:UITableViewRowAnimationRight];
[self.tableView reloadRowsAtIndexPaths:self.updatedRowIndexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
}
// nil out the collections so their ready for their next use.
self.insertedSectionIndexes = nil;
self.deletedSectionIndexes = nil;
self.deletedRowIndexPaths = nil;
self.insertedRowIndexPaths = nil;
self.updatedRowIndexPaths = nil;
}
#pragma mark - Overridden getters
/**
* Lazily instantiate these collections.
*/
- (NSMutableIndexSet *)deletedSectionIndexes
{
if (_deletedSectionIndexes == nil) {
_deletedSectionIndexes = [[NSMutableIndexSet alloc] init];
}
return _deletedSectionIndexes;
}
- (NSMutableIndexSet *)insertedSectionIndexes
{
if (_insertedSectionIndexes == nil) {
_insertedSectionIndexes = [[NSMutableIndexSet alloc] init];
}
return _insertedSectionIndexes;
}
- (NSMutableArray *)deletedRowIndexPaths
{
if (_deletedRowIndexPaths == nil) {
_deletedRowIndexPaths = [[NSMutableArray alloc] init];
}
return _deletedRowIndexPaths;
}
- (NSMutableArray *)insertedRowIndexPaths
{
if (_insertedRowIndexPaths == nil) {
_insertedRowIndexPaths = [[NSMutableArray alloc] init];
}
return _insertedRowIndexPaths;
}
- (NSMutableArray *)updatedRowIndexPaths
{
if (_updatedRowIndexPaths == nil) {
_updatedRowIndexPaths = [[NSMutableArray alloc] init];
}
return _updatedRowIndexPaths;
}
@end
@hborders
Copy link

hborders commented Jun 8, 2015

What is the license for this gist?

@tonnylitao
Copy link

//for insert section, does it also need below code?

case NSFetchedResultsChangeInsert:
            [self.insertedSectionIndexes addIndex:sectionIndex];

            NSMutableArray *indexPathsInSection = [NSMutableArray array];
            for(NSIndexPath *indexPath in self.insertedRowIndexPaths)
            {
                if (indexPath.section == sectionIndex)
                {
                    [indexPathsInSection addObject:indexPath];
                }
            }
            [self.insertedRowIndexPaths removeObjectsInArray:indexPathsInSection];
            break;
        }

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