I want to update the data source of a table view with animations (like with NSFetchedResultsController) but without core data.
There may be objects that were added, objects that were removed, objects that were moved etc...
Is it possible?
I want to update the data source of a table view with animations (like with NSFetchedResultsController) but without core data.
There may be objects that were added, objects that were removed, objects that were moved etc...
Is it possible?
Take a look at TLIndexPathTools. It is an alternative to NSFetchedResultsController
that, in addition to working with NSFetchRequest
and Core Data objects, also works with plain arrays containing any type of data.
It provides a standardized data model class TLIndexPathDataModel
that can automatically organize your data into sections and has many APIs to simplify the implementation of your data source and delegate methods. But the main thing it does is automatically calculate and perform the animated batch updates for you when you update the data model.
Try running the numerous sample projects to get an idea what can be done. The Shuffle sample project is a good starting point: tap the Shuffle button and the collection view grid randomly rearranges itself with animation. Here is the full source of the Shuffle view controller:
#import "TLCollectionViewController.h"
@interface ShuffleCollectionViewController : TLCollectionViewController <UICollectionViewDelegateFlowLayout>
- (IBAction)shuffle;
@end
#import <QuartzCore/QuartzCore.h>
#import "ShuffleCollectionViewController.h"
#import "TLIndexPathDataModel.h"
#import "UIColor+Hex.h"
#define IDX_TEXT 0
#define IDX_COLOR 1
@implementation ShuffleCollectionViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//initialize the controller with a list data items. To keep it simple, we'll
//just use two element arrays (text and color) for our items.
NSArray *items = @[
@[@"A", [UIColor colorWithHexRGB:0x96D6C1]],
@[@"B", [UIColor colorWithHexRGB:0xD696A3]],
@[@"C", [UIColor colorWithHexRGB:0xFACB96]],
@[@"D", [UIColor colorWithHexRGB:0xFAED96]],
@[@"E", [UIColor colorWithHexRGB:0x96FAC3]],
@[@"F", [UIColor colorWithHexRGB:0x6AA9CF]],
];
self.indexPathController.items = items;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [super collectionView:collectionView cellForItemAtIndexPath:indexPath];
//retrieve the cell data for the given index path from the controller
//and set the cell's text label and background color
NSArray *item = [self.indexPathController.dataModel itemAtIndexPath:indexPath];
UILabel *label = (UILabel *)[cell viewWithTag:1];
label.text = item[IDX_TEXT];
cell.backgroundColor = item[IDX_COLOR];
cell.layer.cornerRadius = 10;
return cell;
}
- (void)shuffle
{
//shuffle the items randomly and update the controller with the shuffled items
NSMutableArray *shuffledItems = [NSMutableArray arrayWithArray:self.indexPathController.items];
NSInteger count = shuffledItems.count;
for (int i = 0; i < count; i++) {
[shuffledItems exchangeObjectAtIndex:i withObjectAtIndex:arc4random() % count];
}
self.indexPathController.items = shuffledItems;
}
@end
This example derives from the provided TLCollectionViewController
base class, but you can easily integrate TLIndexPathTools into your own view controllers by copy/pasting from TLCollectionViewController
(there is very little going on there).
It also improves on NSFetchedResultsController
in some respects. First, your items do not need to be pre-sorted to be organized into sections. Secondly, you can do animated sorting and filtering (if you change the sort descriptors or predicate with NSFetchedResultsController
, you've got re-execute the fetch and you won't get animation). Try running the Core Data sample project.
The current version is designed to scale to 1000s of items. So if you've got a really large data set, you might run into performance issues.
Thanks to @IanL I have used the next solution:
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];