From b7629983360d52e170bf73395bfe50ce97193fc4 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Thu, 17 Nov 2016 18:21:27 -0800 Subject: [PATCH] Add detection for a loop if invalidation of a size is happening multiple times --- AsyncDisplayKit/ASDisplayNode.mm | 10 +++++++++- AsyncDisplayKit/Private/ASDisplayNodeLayout.h | 5 +++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index c9a7466c74..83ba52dca2 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1539,7 +1539,15 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) // If the size of the new layout to apply did change from the current bounds, invalidate the whole tree up // so the root node can handle a resizing if necessary - if (CGSizeEqualToSize(ASCeilSizeValues(bounds.size), pendingLayout->layout.size) == NO) { + if (pendingLayout->requestedLayoutFromAbove == NO && + CGSizeEqualToSize(ASCeilSizeValues(bounds.size), pendingLayout->layout.size) == NO) { + // The layout that we have specifies that this node (self) would like to be a different size + // than it currently is. Because that size has been computed within the constrainedSize, we + // expect that doing setNeedsLayoutFromAbove will result in our parent resizing us to this. + // However, in some cases apps may manually interfere with this (setting a different bounds). + // In this case, we need to detect that we've already asked to be resized to match this + // particular ASLayout object, and shouldn't loop asking again unless we have a different ASLayout. + pendingLayout->requestedLayoutFromAbove = YES; [self setNeedsLayoutFromAbove]; } diff --git a/AsyncDisplayKit/Private/ASDisplayNodeLayout.h b/AsyncDisplayKit/Private/ASDisplayNodeLayout.h index 64837acc25..a9a2d5a8a7 100644 --- a/AsyncDisplayKit/Private/ASDisplayNodeLayout.h +++ b/AsyncDisplayKit/Private/ASDisplayNodeLayout.h @@ -24,6 +24,7 @@ struct ASDisplayNodeLayout { ASLayout *layout; ASSizeRange constrainedSize; CGSize parentSize; + BOOL requestedLayoutFromAbove; BOOL _dirty; /* @@ -33,13 +34,13 @@ struct ASDisplayNodeLayout { * @param parentSize Parent size used to create the layout */ ASDisplayNodeLayout(ASLayout *layout, ASSizeRange constrainedSize, CGSize parentSize) - : layout(layout), constrainedSize(constrainedSize), parentSize(parentSize), _dirty(NO) {}; + : layout(layout), constrainedSize(constrainedSize), parentSize(parentSize), requestedLayoutFromAbove(NO), _dirty(NO) {}; /* * Creates a layout without any layout associated. By default this display node layout is dirty. */ ASDisplayNodeLayout() - : layout(nil), constrainedSize({{0, 0}, {0, 0}}), parentSize({0, 0}), _dirty(YES) {}; + : layout(nil), constrainedSize({{0, 0}, {0, 0}}), parentSize({0, 0}), requestedLayoutFromAbove(NO), _dirty(YES) {}; /** * Returns if the display node layout is dirty as it was invalidated or it was created without a layout.