I previously wrote about how to implement NSFetchedResultsController with Magical Record (UITableView version) .
For UICollectionView
, it is largely the same.
Except for the change that Apple did – there is NO [collectionView beginUpdates/endUpdates]
methods.
Therefore, a working implementation for the 4 Crazy NSFetchedResultsControllerDelegate methods is needed to the earlier post .
The code below is exactly from Jose , who adapted the code from AshFurrow . Credits to them.
Firstly, you have to add 2 NSMutableArray
to your view controller to store the changes.
1
2
3
4
@interface MyViewController ()
@property NSMutableArray * sectionChanges ;
@property NSMutableArray * itemChanges ;
@end
In the 4 Crazy NSFetchedResultsControllerDelegate methods, you bascially add to the arrays, and finally update them in batches in controllerDidChangeContent
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
- ( void ) controllerWillChangeContent: ( NSFetchedResultsController * ) controller {
_sectionChanges = [[ NSMutableArray alloc ] init ];
_itemChanges = [[ NSMutableArray alloc ] init ];
}
- ( void ) controller: ( NSFetchedResultsController * ) controller
didChangeSection: ( id < NSFetchedResultsSectionInfo > ) sectionInfo
atIndex: ( NSUInteger ) sectionIndex
forChangeType: ( NSFetchedResultsChangeType ) type {
NSMutableDictionary * change = [[ NSMutableDictionary alloc ] init ];
change [ @ ( type )] = @ ( sectionIndex );
[ _sectionChanges addObject: change ];
}
- ( void ) controller: ( NSFetchedResultsController * ) controller
didChangeObject: ( id ) anObject
atIndexPath: ( NSIndexPath * ) indexPath
forChangeType: ( NSFetchedResultsChangeType ) type
newIndexPath: ( NSIndexPath * ) newIndexPath {
NSMutableDictionary * change = [[ NSMutableDictionary alloc ] init ];
switch ( type ) {
case NSFetchedResultsChangeInsert:
change [ @ ( type )] = newIndexPath ;
break ;
case NSFetchedResultsChangeDelete:
change [ @ ( type )] = indexPath ;
break ;
case NSFetchedResultsChangeUpdate:
change [ @ ( type )] = indexPath ;
break ;
case NSFetchedResultsChangeMove:
change [ @ ( type )] = @ [ indexPath , newIndexPath ];
break ;
}
[ _itemChanges addObject: change ];
}
- ( void ) controllerDidChangeContent: ( NSFetchedResultsController * ) controller {
[ self . collectionView performBatchUpdates: ^ {
for ( NSDictionary * change in _sectionChanges ) {
[ change enumerateKeysAndObjectsUsingBlock: ^ ( id key , id obj , BOOL * stop ) {
NSFetchedResultsChangeType type = [ key unsignedIntegerValue ];
switch ( type ) {
case NSFetchedResultsChangeInsert:
[ self . collectionView insertSections: [ NSIndexSet indexSetWithIndex: [ obj unsignedIntegerValue ]]];
break ;
case NSFetchedResultsChangeDelete:
[ self . collectionView deleteSections: [ NSIndexSet indexSetWithIndex: [ obj unsignedIntegerValue ]]];
break ;
}
}];
}
for ( NSDictionary * change in _itemChanges ) {
[ change enumerateKeysAndObjectsUsingBlock: ^ ( id key , id obj , BOOL * stop ) {
NSFetchedResultsChangeType type = [ key unsignedIntegerValue ];
switch ( type ) {
case NSFetchedResultsChangeInsert:
[ self . collectionView insertItemsAtIndexPaths: @ [ obj ]];
break ;
case NSFetchedResultsChangeDelete:
[ self . collectionView deleteItemsAtIndexPaths: @ [ obj ]];
break ;
case NSFetchedResultsChangeUpdate:
[ self . collectionView reloadItemsAtIndexPaths: @ [ obj ]];
break ;
case NSFetchedResultsChangeMove:
[ self . collectionView moveItemAtIndexPath: obj [ 0 ] toIndexPath: obj [ 1 ]];
break ;
}
}];
}
} completion: ^ ( BOOL finished ) {
_sectionChanges = nil ;
_itemChanges = nil ;
}];
}