Permalink
Browse files

Assemble a dictionary of views that are to be removed

The previous implementation would check if a given PSTCollectionViewItemKey is
present in the new visible views dictionary. This did not work for the following
case:

Item [0,0]
Item [0,1]
Item [0,2]

Deleting item at [0,1] should result in the alpha fade and eventual removal
from the superview and recycle, but actually since [0,1] is a valid index in the
new layout, [0,2] gets removed instead.

This solution adds views that are to be deleted into a specific NSDictionary
that gets enumerated after all animations are finished. All views contained
inside are recycled.
  • Loading branch information...
1 parent 985a605 commit 6c0ab0be0840ca18b30a254b4895e0fdc513bbc3 @alexanderedge alexanderedge committed Mar 14, 2013
Showing with 44 additions and 22 deletions.
  1. +44 −22 PSTCollectionView/PSTCollectionView.m
@@ -1576,6 +1576,11 @@ - (void)updateWithItems:(NSArray *)items {
NSMutableArray *animations = [[NSMutableArray alloc] init];
NSMutableDictionary *newAllVisibleView = [[NSMutableDictionary alloc] init];
+ NSMutableDictionary *viewsToRemove = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ [NSMutableArray array], @(PSTCollectionViewItemTypeCell),
+ [NSMutableArray array], @(PSTCollectionViewItemTypeDecorationView),
+ [NSMutableArray array], @(PSTCollectionViewItemTypeSupplementaryView),nil];
+
for (PSTCollectionViewUpdateItem *updateItem in items) {
if (updateItem.isSectionOperation) continue;
@@ -1593,8 +1598,13 @@ - (void)updateWithItems:(NSArray *)items {
finalAttrs.alpha = 0;
}
[animations addObject:@{@"view": view, @"previousLayoutInfos": startAttrs, @"newLayoutInfos": finalAttrs}];
- [_allVisibleViewsDict removeObjectForKey:key];
+
+ //[_allVisibleViewsDict removeObjectForKey:key];
+
+ [viewsToRemove[@(key.type)] addObject:view];
+
}
+
}
else if(updateItem.updateAction == PSTCollectionUpdateActionInsert) {
NSIndexPath *indexPath = updateItem.indexPathAfterUpdate;
@@ -1659,13 +1669,15 @@ - (void)updateWithItems:(NSArray *)items {
newGlobalIndex = [oldToNewIndexMap[oldGlobalIndex] intValue];
}
NSIndexPath *newIndexPath = newGlobalIndex == NSNotFound ? nil : [_update[@"newModel"] indexPathForItemAtGlobalIndex:newGlobalIndex];
+ NSIndexPath *oldIndexPath = oldGlobalIndex == NSNotFound ? nil : [_update[@"oldModel"] indexPathForItemAtGlobalIndex:oldGlobalIndex];
+
if (newIndexPath) {
PSTCollectionViewLayoutAttributes* startAttrs = nil;
PSTCollectionViewLayoutAttributes* finalAttrs = nil;
-
- startAttrs = [_layout initialLayoutAttributesForAppearingItemAtIndexPath:newIndexPath];
+
+ startAttrs = [_layout initialLayoutAttributesForAppearingItemAtIndexPath:oldIndexPath];
finalAttrs = [_layout layoutAttributesForItemAtIndexPath:newIndexPath];
NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:@{@"view":view}];
@@ -1676,6 +1688,7 @@ - (void)updateWithItems:(NSArray *)items {
PSTCollectionViewItemKey* newKey = [key copy];
[newKey setIndexPath:newIndexPath];
newAllVisibleView[newKey] = view;
+
}
} else if (key.type == PSTCollectionViewItemTypeSupplementaryView) {
PSTCollectionViewLayoutAttributes* startAttrs = nil;
@@ -1712,20 +1725,23 @@ - (void)updateWithItems:(NSArray *)items {
}
NSDictionary *previouslyVisibleViewsDict = _allVisibleViewsDict;
+
_allVisibleViewsDict = newAllVisibleView;
for(NSDictionary *animation in animations) {
PSTCollectionReusableView *view = animation[@"view"];
PSTCollectionViewLayoutAttributes *attr = animation[@"previousLayoutInfos"];
[view applyLayoutAttributes:attr];
};
-
+
+
+
[UIView animateWithDuration:.3 animations:^{
_collectionViewFlags.updatingLayout = YES;
[CATransaction begin];
[CATransaction setAnimationDuration:.3];
-
+
// You might wonder why we use CATransaction to handle animation completion
// here instead of using the completion: parameter of UIView's animateWithDuration:.
// The problem is that animateWithDuration: calls this completion block
@@ -1741,33 +1757,39 @@ - (void)updateWithItems:(NSArray *)items {
// to call _updateCompletionHandler with that flag.
// Ideally, _updateCompletionHandler should be called along with the other logic in
// CATransaction's completionHandler but I simply don't know where to get that flag.
-
+
[CATransaction setCompletionBlock:^{
- // Iterate through all the views previously visible and search for those which are no more visible.
- [previouslyVisibleViewsDict enumerateKeysAndObjectsUsingBlock:
- ^(PSTCollectionViewItemKey *key, PSTCollectionReusableView* view, BOOL *stop) {
- if (!_allVisibleViewsDict[key]) {
- // View for this key isn't visible any more, so it should be reused.
- if(key.type == PSTCollectionViewItemTypeCell) {
- [self reuseCell:(PSTCollectionViewCell *)view];
- } else if (key.type == PSTCollectionViewItemTypeSupplementaryView) {
- [self reuseSupplementaryView:view];
- } else if (key.type == PSTCollectionViewItemTypeDecorationView) {
- [self reuseDecorationView:view];
- }
- }
- }];
-
+ // Iterate through all the views that we are going to remove.
+
+ [viewsToRemove enumerateKeysAndObjectsUsingBlock:^(NSNumber *keyObj, NSArray *array, BOOL *stop) {
+
+ PSTCollectionViewItemType type = [keyObj unsignedIntegerValue];
+
+ [array enumerateObjectsUsingBlock:^(id view, NSUInteger idx, BOOL *stop) {
+
+ if(type == PSTCollectionViewItemTypeCell) {
+ [self reuseCell:(PSTCollectionViewCell *)view];
+ } else if (type == PSTCollectionViewItemTypeSupplementaryView) {
+ [self reuseSupplementaryView:view];
+ } else if (type == PSTCollectionViewItemTypeDecorationView) {
+ [self reuseDecorationView:view];
+ }
+
+ }];
+
+ }];
+
_collectionViewFlags.updatingLayout = NO;
}];
-
+
for (NSDictionary *animation in animations) {
PSTCollectionReusableView* view = animation[@"view"];
PSTCollectionViewLayoutAttributes* attrs = animation[@"newLayoutInfos"];
[view applyLayoutAttributes:attrs];
}
[CATransaction commit];
} completion:^(BOOL finished) {
+
if(_updateCompletionHandler) {
_updateCompletionHandler(finished);
_updateCompletionHandler = nil;

0 comments on commit 6c0ab0b

Please sign in to comment.