Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ASCollectionView] Improve performance and behavior of rotation / bounds changes. #431

Merged
merged 9 commits into from
Oct 24, 2017
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## master

* Add your own contributions to the next release on the line below this with your name.
- [ASCollectionView] Improve performance and behavior of rotation / bounds changes. [Scott Goodson](https://github.com/appleguy) [#431](https://github.com/TextureGroup/Texture/pull/431)
- [ASCollectionView] Improve index space translation of Flow Layout Delegate methods. [Scott Goodson](https://github.com/appleguy)
- [ASVideoNode] Fix unreleased time observer. [Flo Vouin](https://github.com/flovouin)
- [PINCache] Set a default .byteLimit to reduce disk usage and startup time. [#595](https://github.com/TextureGroup/Texture/pull/595) [Scott Goodson](https://github.com/appleguy)
Expand Down
11 changes: 6 additions & 5 deletions Source/ASCollectionView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,9 @@ - (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICol

- (void)relayoutItems
{
[_dataController relayoutAllNodes];
[_dataController relayoutAllNodesWithInvalidationBlock:^{
[self.collectionViewLayout invalidateLayout];
}];
}

- (BOOL)isProcessingUpdates
Expand Down Expand Up @@ -2271,10 +2273,9 @@ - (void)layer:(CALayer *)layer didChangeBoundsWithOldValue:(CGRect)oldBounds new
BOOL changedInNonScrollingDirection = (fixedHorizontally && newBounds.size.width != lastUsedSize.width) || (fixedVertically && newBounds.size.height != lastUsedSize.height);

if (changedInNonScrollingDirection) {
[_dataController relayoutAllNodes];
[_dataController waitUntilAllUpdatesAreProcessed];
// We need to ensure the size requery is done before we update our layout.
[self.collectionViewLayout invalidateLayout];
[_dataController relayoutAllNodesWithInvalidationBlock:^{
[self.collectionViewLayout invalidateLayout];
}];
}
}

Expand Down
4 changes: 2 additions & 2 deletions Source/ASTableView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ - (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITabl

- (void)relayoutItems
{
[_dataController relayoutAllNodes];
[_dataController relayoutAllNodesWithInvalidationBlock:nil];
}

- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType
Expand Down Expand Up @@ -760,7 +760,7 @@ - (void)layoutSubviews
_nodesConstrainedWidth = constrainedWidth;

[self beginUpdates];
[_dataController relayoutAllNodes];
[_dataController relayoutAllNodesWithInvalidationBlock:nil];
[self endUpdatesAnimated:(ASDisplayNodeLayerHasAnimations(self.layer) == NO) completion:nil];
} else {
if (_cellsForLayoutUpdates.count > 0) {
Expand Down
5 changes: 4 additions & 1 deletion Source/Details/ASDataController.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,11 @@ extern NSString * const ASCollectionInvalidUpdateException;
*
* @discussion Used to respond to a change in size of the containing view
* (e.g. ASTableView or ASCollectionView after an orientation change).
*
* The invalidationBlock is called after flushing the ASMainSerialQueue, which ensures that any in-progress
* layout calculations have been applied. The block will not be called if data hasn't been loaded.
*/
- (void)relayoutAllNodes;
- (void)relayoutAllNodesWithInvalidationBlock:(nullable void (^)())invalidationBlock;

/**
* Re-measures given nodes in the backing store.
Expand Down
9 changes: 8 additions & 1 deletion Source/Details/ASDataController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ - (void)relayoutNodes:(id<NSFastEnumeration>)nodes nodesSizeChanged:(NSMutableAr
}
}

- (void)relayoutAllNodes
- (void)relayoutAllNodesWithInvalidationBlock:(nullable void (^)())invalidationBlock
{
ASDisplayNodeAssertMainThread();
if (!_initialReloadDataHasBeenCalled) {
Expand All @@ -770,6 +770,13 @@ - (void)relayoutAllNodes
// i.e there might be some nodes that were measured using the old constrained size but haven't been added to _visibleMap
LOG(@"Edit Command - relayoutRows");
[self _scheduleBlockOnMainSerialQueue:^{
// Because -invalidateLayout doesn't trigger any operations by itself, and we answer queries from UICollectionView using layoutThatFits:,
// we invalidate the layout before we have updated all of the cells. Any cells that the collection needs the size of immediately will get
// -layoutThatFits: with a new constraint, on the main thread, and synchronously calculate them. Meanwhile, relayoutAllNodes will update
// the layout of any remaining nodes on background threads (and fast-return for any nodes that the UICV got to first).
if (invalidationBlock) {
invalidationBlock();
}
[self _relayoutAllNodes];
}];
}
Expand Down
4 changes: 2 additions & 2 deletions Tests/ASTableViewTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ @interface ASTestDataController : ASDataController

@implementation ASTestDataController

- (void)relayoutAllNodes
- (void)relayoutAllNodesWithInvalidationBlock:(nullable void (^)())invalidationBlock
{
_numberOfAllNodesRelayouts++;
[super relayoutAllNodes];
[super relayoutAllNodesWithInvalidationBlock:invalidationBlock];
}

@end
Expand Down