diff --git a/Source/ASDisplayNode+Layout.mm b/Source/ASDisplayNode+Layout.mm index f7dfa006ba..6cc2d40599 100644 --- a/Source/ASDisplayNode+Layout.mm +++ b/Source/ASDisplayNode+Layout.mm @@ -73,7 +73,7 @@ - (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 @@ -81,23 +81,26 @@ 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(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( - [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