diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 3f8604ff9d..df464cb48c 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1382,17 +1382,28 @@ ASLayoutableSizeHelperForwarding - (void)measureNodeWithBoundsIfNecessary:(CGRect)bounds { + BOOL supportsRangeManagedInterfaceState = NO; BOOL hasDirtyLayout = NO; CGSize calculatedLayoutSize = CGSizeZero; { ASDN::MutexLocker l(__instanceLock__); + supportsRangeManagedInterfaceState = [self supportsRangeManagedInterfaceState]; hasDirtyLayout = _calculatedDisplayNodeLayout->isDirty(); calculatedLayoutSize = _calculatedDisplayNodeLayout->layout.size; } + + // Check if it's a subnode in a layout transition. In this case no measurement is needed as it's part of + // the layout transition + if (ASHierarchyStateIncludesLayoutPending(_hierarchyState)) { + ASLayoutableContext context = ASLayoutableGetCurrentContext(); + if (ASLayoutableContextIsNull(context) || _pendingTransitionID != context.transitionID) { + return; + } + } // If no measure pass happened or the bounds changed between layout passes we manually trigger a measurement pass // for the node using a size range equal to whatever bounds were provided to the node - if (hasDirtyLayout || CGSizeEqualToSize(calculatedLayoutSize, bounds.size) == NO) { + if (supportsRangeManagedInterfaceState == NO && (hasDirtyLayout || CGSizeEqualToSize(calculatedLayoutSize, bounds.size) == NO)) { if (CGRectEqualToRect(bounds, CGRectZero)) { LOG(@"Warning: No size given for node before node was trying to layout itself: %@. Please provide a frame for the node.", self); } else { diff --git a/AsyncDisplayKitTests/ASDisplayNodeLayoutTests.mm b/AsyncDisplayKitTests/ASDisplayNodeLayoutTests.mm index 9b38bf5fa4..aa7f0ff279 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeLayoutTests.mm +++ b/AsyncDisplayKitTests/ASDisplayNodeLayoutTests.mm @@ -44,31 +44,6 @@ ASXCTAssertEqualSizes(buttonNode.calculatedSize, nodeSize, @"Automatic measurement pass should have happened in layout pass"); } -- (void)testMeasureOnLayoutIfNotHappenedBeforeForRangeManagedNodes -{ - CGSize nodeSize = CGSizeMake(100, 100); - - ASDisplayNode *displayNode = [ASDisplayNode new]; - [displayNode setSizeWithCGSize:nodeSize]; - - ASButtonNode *buttonNode = [ASButtonNode new]; - [displayNode addSubnode:buttonNode]; - - [displayNode enterHierarchyState:ASHierarchyStateRangeManaged]; - - displayNode.frame = {.size = nodeSize}; - buttonNode.frame = {.size = nodeSize}; - - ASXCTAssertEqualSizes(displayNode.calculatedSize, CGSizeZero, @"Calculated size before measurement and layout should be 0"); - ASXCTAssertEqualSizes(buttonNode.calculatedSize, CGSizeZero, @"Calculated size before measurement and layout should be 0"); - - // Trigger layout pass without a maeasurment pass before - [displayNode.view layoutIfNeeded]; - - ASXCTAssertEqualSizes(displayNode.calculatedSize, nodeSize, @"Automatic measurement pass should have happened in layout pass"); - ASXCTAssertEqualSizes(buttonNode.calculatedSize, nodeSize, @"Automatic measurement pass should have happened in layout pass"); -} - #if DEBUG - (void)testNotAllowAddingSubnodesInLayoutSpecThatFits { diff --git a/AsyncDisplayKitTests/ASDisplayNodeTests.m b/AsyncDisplayKitTests/ASDisplayNodeTests.m index dfe8d470eb..43f9a3ed78 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeTests.m @@ -1988,7 +1988,7 @@ static bool stringContainsPointer(NSString *description, id p) { // FIXME // Supernode is measured, subnode isnt, transition starts, UIKit does a layout pass before measurement finishes -- (void)DISABLED_testThatItsSafeToAutomeasureANodeMidTransition +- (void)testThatItsSafeToAutomeasureANodeMidTransition { ASDisplayNode *supernode = [[ASDisplayNode alloc] init]; [supernode layoutThatFits:ASSizeRangeMake(CGSizeZero, CGSizeMake(100, 100))];