Skip to content

Commit

Permalink
Calls to -beginUpdates and -endUpdates can now be nested. It's inadvi…
Browse files Browse the repository at this point in the history
…sable to try and make the same items animate twice at the same time though.
  • Loading branch information
Jim Dovey committed Jun 23, 2010
1 parent 80304f2 commit 848560e
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 46 deletions.
5 changes: 3 additions & 2 deletions Classes/AQGridView.h
Expand Up @@ -93,6 +93,7 @@ extern NSString * const AQGridViewSelectionDidChangeNotification;

AQGridViewData * _gridData;
NSMutableArray * _updateInfoStack;
NSInteger _animationCount;

CGRect _visibleBounds;
NSRange _visibleIndices;
Expand Down Expand Up @@ -128,13 +129,13 @@ extern NSString * const AQGridViewSelectionDidChangeNotification;
unsigned separatorStyle:3;
unsigned allowsSelection:1;
unsigned usesPagedHorizontalScrolling:1;
unsigned updating:1;
unsigned updating:1; // unused
unsigned ignoreTouchSelect:1;
unsigned needsReload:1;
unsigned allCellsNeedLayout:1;
unsigned isRotating:1;
unsigned clipsContentWidthToBounds:1;
unsigned isAnimatingUpdates:1;
unsigned isAnimatingUpdates:1; // unused, see _animationCount instead
unsigned requiresSelection:1;
unsigned contentSizeFillsBounds:1;

Expand Down
70 changes: 26 additions & 44 deletions Classes/AQGridView.m
Expand Up @@ -378,7 +378,7 @@ - (void) setContentSizeGrowsToFillBounds: (BOOL) value

- (BOOL) isAnimatingUpdates
{
return ( _flags.isAnimatingUpdates == 1 );
return ( _animationCount > 0 );
}

- (void) updateContentRectWithOldMaxLocation: (CGPoint) oldMaxLocation gridSize: (CGSize) gridSize
Expand All @@ -394,7 +394,7 @@ - (void) updateContentRectWithOldMaxLocation: (CGPoint) oldMaxLocation gridSize:
{
offset.y = MAX(0.0, self.contentSize.height - self.bounds.size.height);
}
else
else if ( !CGPointEqualToPoint(oldOffset, CGPointZero) ) // stick-to-top takes precedence
{
if ( [_gridData pointIsInLastRow: oldMaxLocation] )
{
Expand All @@ -406,7 +406,7 @@ - (void) updateContentRectWithOldMaxLocation: (CGPoint) oldMaxLocation gridSize:
}
}

NSLog( @"Resetting offset from %@ to %@", NSStringFromCGPoint(oldOffset), NSStringFromCGPoint(offset) );
//NSLog( @"Resetting offset from %@ to %@", NSStringFromCGPoint(oldOffset), NSStringFromCGPoint(offset) );
self.contentOffset = offset;
}

Expand All @@ -422,7 +422,7 @@ - (void) handleGridViewBoundsChanged: (CGRect) oldBounds toNewBounds: (CGRect) b
CGPoint oldMaxLocation = CGPointMake(CGRectGetMaxX(oldBounds), CGRectGetMaxY(oldBounds));
[self updateContentRectWithOldMaxLocation: oldMaxLocation gridSize: newGridSize];

if ( (wasAtBottom) && (newGridSize.height > oldGridSize.height) )
if ( (wasAtBottom) && (!CGPointEqualToPoint(oldBounds.origin, CGPointZero)) && (newGridSize.height > oldGridSize.height) )
{
CGRect contentRect = self.bounds;
if ( CGRectGetMaxY(contentRect) < newGridSize.height )
Expand Down Expand Up @@ -575,7 +575,7 @@ - (void) reloadData

- (void) layoutSubviews
{
if ( (_flags.needsReload == 1) && (_flags.updating == 0) && (_reloadingSuspendedCount == 0) )
if ( (_flags.needsReload == 1) && (_animationCount == 0) && (_reloadingSuspendedCount == 0) )
[self reloadData];

if ( (_reloadingSuspendedCount == 0) && (!CGRectIsEmpty([self gridViewVisibleBounds])) )
Expand Down Expand Up @@ -729,7 +729,7 @@ - (void) fixCellsFromAnimation
}

_visibleIndices.location = [indices firstIndex];
_visibleIndices.length = ([indices lastIndex] - [indices firstIndex]) + 1;
_visibleIndices.length = [indices count];

NSMutableArray * newVisibleCells = [[NSMutableArray alloc] initWithCapacity: _visibleIndices.length];
for ( UIView * potentialCellView in self.animatingCells )
Expand Down Expand Up @@ -779,8 +779,6 @@ - (void) fixCellsFromAnimation

- (void) setupUpdateAnimations
{
_flags.updating = 1;
_flags.isAnimatingUpdates = 1;
_reloadingSuspendedCount++;

AQGridViewUpdateInfo * info = [[AQGridViewUpdateInfo alloc] initWithOldGridData: _gridData forGridView: self];
Expand All @@ -797,12 +795,6 @@ - (void) endUpdateAnimations
if ( info.numberOfUpdates == 0 )
{
[_updateInfoStack removeLastObject];
if ( [_updateInfoStack count] == 0 )
{
_flags.updating = 0;
_flags.isAnimatingUpdates = 0;
}

return;
}

Expand All @@ -814,16 +806,12 @@ - (void) endUpdateAnimations
NSUInteger numDeleted = [[info sortedDeleteItems] count];

[_updateInfoStack removeLastObject];
if ( [_updateInfoStack count] == 0 )
{
_flags.updating = 0;
_flags.isAnimatingUpdates = 0;
}

[NSException raise: NSInternalInconsistencyException format: @"Invalid number of items in AQGridView: Started with %u, added %u, deleted %u. Expected %u items after changes, but got %u", (unsigned)_gridData.numberOfItems, (unsigned)numAdded, (unsigned)numDeleted, (unsigned)expectedItemCount, (unsigned)actualItemCount];
}

[info cleanupUpdateItems];
_animationCount++;

[UIView beginAnimations: @"CellUpdates" context: info];
[UIView setAnimationDelegate: self];
Expand All @@ -839,9 +827,6 @@ - (void) endUpdateAnimations
_gridData = [[info newGridViewData] retain];
if ( _selectedIndex != NSNotFound )
_selectedIndex = [info newIndexForOldIndex: _selectedIndex];

if ( [_updateInfoStack count] == 1 )
_flags.updating = 0;
}

- (void) cellUpdateAnimationStopped: (NSString *) animationID finished: (BOOL) finished context: (void *) context
Expand All @@ -854,11 +839,7 @@ - (void) cellUpdateAnimationStopped: (NSString *) animationID finished: (BOOL) f

// NB: info becomes invalid at this point
[_updateInfoStack removeObject: info];
if ( [_updateInfoStack count] == 0 )
{
_flags.updating = 0;
_flags.isAnimatingUpdates = 0;
}
_animationCount--;

//_reloadingSuspendedCount--;
}
Expand All @@ -877,16 +858,16 @@ - (void) endUpdates

- (void) _updateItemsAtIndices: (NSIndexSet *) indices updateAction: (AQGridViewUpdateAction) action withAnimation: (AQGridViewItemAnimation) animation
{
BOOL wasUpdating = (_flags.updating == 1);
BOOL needsAnimationSetup = ([_updateInfoStack count] == 1);

// not in the middle of an update loop -- start animations here
if ( wasUpdating == NO )
if ( needsAnimationSetup )
[self setupUpdateAnimations];

[[_updateInfoStack lastObject] updateItemsAtIndices: indices updateAction: action withAnimation: animation];

// not in the middle of an update loop -- commit animations here
if ( wasUpdating == NO )
if ( needsAnimationSetup )
[self endUpdateAnimations];
}

Expand All @@ -907,14 +888,14 @@ - (void) reloadItemsAtIndices: (NSIndexSet *) indices withAnimation: (AQGridView

- (void) moveItemAtIndex: (NSUInteger) index toIndex: (NSUInteger) newIndex withAnimation: (AQGridViewItemAnimation) animation
{
BOOL wasUpdating = (_flags.updating == 1);
BOOL needsAnimationSetup = ([_updateInfoStack count] == 1);

if ( wasUpdating == NO )
if ( needsAnimationSetup )
[self setupUpdateAnimations];

[[_updateInfoStack lastObject] moveItemAtIndex: index toIndex: newIndex withAnimation: animation];

if ( wasUpdating == NO )
if ( needsAnimationSetup )
[self endUpdateAnimations];
}

Expand Down Expand Up @@ -1331,7 +1312,7 @@ - (void) updateVisibleGridCellsNow
if ( _reloadingSuspendedCount > 0 )
return;

if ( _flags.isAnimatingUpdates || _flags.updating )
if ( _animationCount > 0 )
return;

_reloadingSuspendedCount++;
Expand All @@ -1342,7 +1323,7 @@ - (void) updateVisibleGridCellsNow
if ( ([_visibleCells count] != [newVisibleIndices count]) ||
([newVisibleIndices countOfIndexesInRange: _visibleIndices] != _visibleIndices.length) )
{
NSLog( @"\n\n----------BEGIN CELL UPDATES----------" );
//NSLog( @"\n\n----------BEGIN CELL UPDATES----------" );
BOOL enableAnim = [UIView areAnimationsEnabled];
[UIView setAnimationsEnabled: NO];

Expand All @@ -1365,26 +1346,26 @@ - (void) updateVisibleGridCellsNow
insertedIndices = [newVisibleIndices aq_indexesOutsideIndexSet: currentVisibleIndices];
}

NSLog( @"Removing indices: %@, inserting indices: %@", removedIndices, insertedIndices );
NSLog( @"Visible cells count = %lu", (unsigned long)[_visibleCells count] );
//NSLog( @"Removing indices: %@, inserting indices: %@", removedIndices, insertedIndices );
//NSLog( @"Visible cells count = %lu", (unsigned long)[_visibleCells count] );

NSInteger deltaCount = (NSInteger)[insertedIndices count] - (NSInteger)[removedIndices count];
NSUInteger newCellCount = [_visibleCells count] + deltaCount;
NSLog( @"Should have %lu cells visible at the end", (unsigned long)newCellCount );
//NSLog( @"Should have %lu cells visible at the end", (unsigned long)newCellCount );
NSAssert( newCellCount == [newVisibleIndices count], @"visible cell count should match visible indices count" );

NSMutableIndexSet * shifted = [removedIndices mutableCopy];

// get an index set for everything being removed relative to items' locations within the visible cell list
[shifted shiftIndexesStartingAtIndex: [removedIndices firstIndex] by: 0 - (NSInteger)_visibleIndices.location];
NSLog( @"Removed indices relative to visible cell list: %@", shifted );
//NSLog( @"Removed indices relative to visible cell list: %@", shifted );

// pull out the cells for manipulation
NSArray * removedCells = [_visibleCells objectsAtIndexes: shifted];

// remove them from the visible list
[_visibleCells removeObjectsAtIndexes: shifted];
NSLog( @"After removals, visible cells count = %lu", (unsigned long)[_visibleCells count] );
//NSLog( @"After removals, visible cells count = %lu", (unsigned long)[_visibleCells count] );

// don't need this any more
[shifted release]; shifted = nil;
Expand All @@ -1398,7 +1379,7 @@ - (void) updateVisibleGridCellsNow
[mutable release];
}

NSLog( @"Removing %lu cells from screen", (unsigned long)[removedCells count] );
//NSLog( @"Removing %lu cells from screen", (unsigned long)[removedCells count] );
[removedCells makeObjectsPerformSelector: @selector(removeFromSuperview)];

// put them into the cell reuse queue
Expand All @@ -1415,19 +1396,20 @@ - (void) updateVisibleGridCellsNow

idx = [insertedIndices indexGreaterThanIndex: idx];
}
NSLog( @"After insertions, visible cells count = %lu", (unsigned long)[_visibleCells count] );

//NSLog( @"After insertions, visible cells count = %lu", (unsigned long)[_visibleCells count] );
NSAssert( [_visibleCells count] == newCellCount, @"Cell count doesn't match what was expected" );

// need to have _visibleIndices setup before calling layout
_visibleIndices.location = [newVisibleIndices firstIndex];
_visibleIndices.length = [newVisibleIndices count];
NSLog( @"New visible indices: %@", NSStringFromRange(_visibleIndices) );
//NSLog( @"New visible indices: %@", NSStringFromRange(_visibleIndices) );

// layout the new cells
[self layoutCellsInVisibleCellRange: NSMakeRange(0, [_visibleCells count])];

[UIView setAnimationsEnabled: enableAnim];
NSLog( @"----------END CELL UPDATES----------\n\n" );
//NSLog( @"----------END CELL UPDATES----------\n\n" );
}

_reloadingSuspendedCount--;
Expand Down

0 comments on commit 848560e

Please sign in to comment.