Last active
August 29, 2015 14:11
-
-
Save honghaoz/3bc6cbec2b22f66962c0 to your computer and use it in GitHub Desktop.
collection view perform batch update
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Compare old data model with new data model and perform batch update for collection view | |
/** | |
* Perform batch update on collection view, use old stories and new stories to make comparison | |
* groupId property of story is used for comparison | |
* | |
* PRE: make sure collection view's data model is update with newArray | |
* | |
* After animation completed, visible cells' view are updated | |
* | |
* @param oldArray Arrary of old stories, contains Story object | |
* @param newArray Arrary of new stories, contains Story object | |
*/ | |
- (void)performBatchUpdateFromOldDataModel:(NSArray *)oldArray toNewDataModel:(NSArray *)newArray | |
{ | |
// For the first time, when collection view is empty, call reloadData | |
if (oldArray.count == 0) | |
{ | |
[self.collectionView reloadData]; | |
return; | |
} | |
// Prepare groupIds for old stories and new stories, use id to compare | |
NSMutableArray *oldStoryIds = [[NSMutableArray alloc] initWithCapacity:oldArray.count]; | |
for (Story *story in oldArray) | |
{ | |
[oldStoryIds addObject:story.groupId]; | |
} | |
NSMutableArray *newStoryIds = [[NSMutableArray alloc] initWithCapacity:newArray.count]; | |
for (Story *story in newArray) | |
{ | |
[newStoryIds addObject:story.groupId]; | |
} | |
// If there's no changes, don't update | |
if ([oldStoryIds isEqualToArray:newStoryIds]) | |
{ | |
return; | |
} | |
// Arrays stores indic to be processed | |
NSMutableArray *deletedIndice = [[NSMutableArray alloc] init]; // [1, 2, 3 ...] | |
NSMutableArray *insertedIndice = [[NSMutableArray alloc] init]; // [1, 2, 3 ...] | |
NSMutableArray *movedIndice = [[NSMutableArray alloc] init]; // [[1, 3], [4, 2] ...] | |
// Old vs New, to initialize deleted indice and moved indice | |
// Init deleted indice, existing in Old but not in New | |
// Init moved indice, existing in both but indice are different | |
NSUInteger oldStoryIdsCount = [oldStoryIds count]; | |
for (NSUInteger oldIdIndex = 0; oldIdIndex < oldStoryIdsCount; oldIdIndex++) | |
{ | |
NSNumber *oldId = [oldStoryIds objectAtIndex:oldIdIndex]; | |
if (![newStoryIds containsObject:oldId]) | |
{ | |
// Deleted | |
[deletedIndice addObject:@(oldIdIndex)]; | |
} | |
else | |
{ | |
NSMutableArray *OldIndexToNewIndex = [[NSMutableArray alloc] initWithCapacity:2]; | |
NSUInteger newIdIndex = [newStoryIds indexOfObject:oldId]; | |
// Moved | |
if (newIdIndex != oldIdIndex) | |
{ | |
OldIndexToNewIndex[0] = @(oldIdIndex); | |
OldIndexToNewIndex[1] = @(newIdIndex); | |
[movedIndice addObject:OldIndexToNewIndex]; | |
} | |
} | |
} | |
// New vs Old, to initialize inserted indice | |
// Init inserted indice, existing in New but not in Old | |
NSUInteger newStoryIdsCount = [newStoryIds count]; | |
for (NSUInteger newIdIndex = 0; newIdIndex < newStoryIdsCount; newIdIndex++) | |
{ | |
NSNumber *newId = [newStoryIds objectAtIndex:newIdIndex]; | |
if (![oldStoryIds containsObject:newId]) | |
{ | |
// Inserted | |
[insertedIndice addObject:@(newIdIndex)]; | |
} | |
} | |
// Perform collection view animation | |
__weak CurrentReadsViewController *weakSelf = self; | |
[self.collectionView performBatchUpdates:^{ | |
// Delete | |
NSArray *deletedIndexPaths = [deletedIndice map:^id(NSNumber *indexToDelete, NSUInteger index) { | |
return [NSIndexPath indexPathForItem:[indexToDelete unsignedIntegerValue] inSection:0]; | |
}]; | |
[weakSelf.collectionView deleteItemsAtIndexPaths:deletedIndexPaths]; | |
// Insert | |
NSArray *insertedIndexPaths = [insertedIndice map:^id(NSNumber *indexToInsert, NSUInteger index) { | |
return [NSIndexPath indexPathForItem:[indexToInsert unsignedIntegerValue] inSection:0]; | |
}]; | |
[weakSelf.collectionView insertItemsAtIndexPaths:insertedIndexPaths]; | |
// Move | |
for (NSArray *oldIndexToNewIndexPair in movedIndice) | |
{ | |
NSUInteger oldIndex = [oldIndexToNewIndexPair[0] unsignedIntegerValue]; | |
NSUInteger newIndex = [oldIndexToNewIndexPair[1] unsignedIntegerValue]; | |
NSIndexPath *fromIndexPath = [NSIndexPath indexPathForItem:oldIndex inSection:0]; | |
NSIndexPath *toIndexPath = [NSIndexPath indexPathForItem:newIndex inSection:0]; | |
[weakSelf.collectionView moveItemAtIndexPath:fromIndexPath toIndexPath:toIndexPath]; | |
} | |
} completion:nil]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment