Skip to content

Commit

Permalink
[ASDisplayNode+Layout] In layoutThatFits:, check and use _pending lay…
Browse files Browse the repository at this point in the history
…out if valid. (TextureGroup#413)

I believe this check is supposed to be here. Unit tests pass with it in place.
Without it, calling layoutThatFits: (as ASDataController does) and then calling
it again later (as ASCollectionNode does when answering the sizeForItem: call)
will recompute the layout, potentially on main.

This seems to have more of an impact / benefit for Yoga layouts, but I don't think
its benefit is exclusive to them.
  • Loading branch information
appleguy authored and bernieperez committed Apr 25, 2018
1 parent ad679c3 commit 1f8ee3f
Showing 1 changed file with 14 additions and 11 deletions.
25 changes: 14 additions & 11 deletions Source/ASDisplayNode+Layout.mm
Original file line number Diff line number Diff line change
Expand Up @@ -73,31 +73,34 @@ - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
- (ASLayout *)layoutThatFits:(ASSizeRange)constrainedSize parentSize:(CGSize)parentSize
{
ASDN::MutexLocker l(__instanceLock__);

// If one or multiple layout transitions are in flight it still can happen that layout information is requested
// on other threads. As the pending and calculated layout to be updated in the layout transition in here just a
// layout calculation wil be performed without side effect
if ([self _isLayoutTransitionInvalid]) {
return [self calculateLayoutThatFits:constrainedSize restrictedToSize:self.style.size relativeToParentSize:parentSize];
}

ASLayout *layout = nil;
if (_calculatedDisplayNodeLayout->isValidForConstrainedSizeParentSize(constrainedSize, parentSize)) {
ASDisplayNodeAssertNotNil(_calculatedDisplayNodeLayout->layout, @"-[ASDisplayNode layoutThatFits:parentSize:] _calculatedDisplayNodeLayout->layout should not be nil! %@", self);
// Our calculated layout is suitable for this constrainedSize, so keep using it and
// invalidate any pending layout that has been generated in the past.
_pendingDisplayNodeLayout = nullptr;
return _calculatedDisplayNodeLayout->layout ?: [ASLayout layoutWithLayoutElement:self size:{0, 0}];
layout = _calculatedDisplayNodeLayout->layout;
} else if (_pendingDisplayNodeLayout != nullptr && _pendingDisplayNodeLayout->isValidForConstrainedSizeParentSize(constrainedSize, parentSize)) {
ASDisplayNodeAssertNotNil(_pendingDisplayNodeLayout->layout, @"-[ASDisplayNode layoutThatFits:parentSize:] _pendingDisplayNodeLayout->layout should not be nil! %@", self);
layout = _pendingDisplayNodeLayout->layout;
} else {
// Create a pending display node layout for the layout pass
layout = [self calculateLayoutThatFits:constrainedSize
restrictedToSize:self.style.size
relativeToParentSize:parentSize];
_pendingDisplayNodeLayout = std::make_shared<ASDisplayNodeLayout>(layout, constrainedSize, parentSize);
ASDisplayNodeAssertNotNil(layout, @"-[ASDisplayNode layoutThatFits:parentSize:] newly calculated layout should not be nil! %@", self);
}

// Create a pending display node layout for the layout pass
_pendingDisplayNodeLayout = std::make_shared<ASDisplayNodeLayout>(
[self calculateLayoutThatFits:constrainedSize restrictedToSize:self.style.size relativeToParentSize:parentSize],
constrainedSize,
parentSize
);

ASDisplayNodeAssertNotNil(_pendingDisplayNodeLayout->layout, @"-[ASDisplayNode layoutThatFits:parentSize:] _pendingDisplayNodeLayout->layout should not be nil! %@", self);
return _pendingDisplayNodeLayout->layout ?: [ASLayout layoutWithLayoutElement:self size:{0, 0}];
return layout ?: [ASLayout layoutWithLayoutElement:self size:{0, 0}];
}

#pragma mark ASLayoutElementStyleExtensibility
Expand Down

0 comments on commit 1f8ee3f

Please sign in to comment.