diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index a06b8bf352..8cf5137719 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1074,19 +1074,58 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) ASDisplayNodeAssertMainThread(); ASDN::MutexLocker l(_propertyLock); CGRect bounds = self.bounds; - if (CGRectEqualToRect(bounds, CGRectZero)) { - // Performing layout on a zero-bounds view often results in frame calculations - // with negative sizes after applying margins, which will cause - // measureWithSizeRange: on subnodes to assert. + + [self measureNodeWithBoundsIfNecessary:bounds]; + + // Performing layout on a zero-bounds view often results in frame calculations + // with negative sizes after applying margins, which will cause + // measureWithSizeRange: on subnodes to assert. + if (!CGRectEqualToRect(bounds, CGRectZero)) { + _placeholderLayer.frame = bounds; + [self layout]; + [self layoutDidFinish]; + } +} + +- (void)measureNodeWithBoundsIfNecessary:(CGRect)bounds +{ + // Normally measure will be called before layout occurs. If this doesn't happen, nothing is going to call it at all. + // We simply call measureWithSizeRange: using a size range equal to whatever bounds were provided to that element or + // try to measure the node with the largest size as possible + if (self.supernode == nil && !self.supportsRangeManagedInterfaceState && !_flags.isMeasured) { + if (CGRectEqualToRect(bounds, CGRectZero)) { + // FIXME: Better log to let developers know that the node was not measured before the layout call and no frame was set + NSLog(@"Warning: No size given for node before node was trying to layout itself: %@. Please provide a frame for the node.", self); + } else { + ASSizeRange measureSizeRange = ASSizeRangeMake(CGSizeZero, bounds.size); + if ([self shouldMeasureWithSizeRange:measureSizeRange]) { + [self measureWithSizeRange:measureSizeRange]; + } + } + } +} + +- (void)layout +{ + ASDisplayNodeAssertMainThread(); + + if (!_flags.isMeasured) { return; } - _placeholderLayer.frame = bounds; - [self layout]; - [self layoutDidFinish]; + + [self __layoutSublayouts]; +} + +- (void)__layoutSublayouts +{ + for (ASLayout *subnodeLayout in _layout.immediateSublayouts) { + ((ASDisplayNode *)subnodeLayout.layoutableObject).frame = [subnodeLayout frame]; + } } - (void)layoutDidFinish { + // Hook for subclasses } - (CATransform3D)_transformToAncestor:(ASDisplayNode *)ancestor @@ -2369,24 +2408,6 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) } } -- (void)layout -{ - ASDisplayNodeAssertMainThread(); - - if (!_flags.isMeasured) { - return; - } - - [self __layoutSublayouts]; -} - -- (void)__layoutSublayouts -{ - for (ASLayout *subnodeLayout in _layout.immediateSublayouts) { - ((ASDisplayNode *)subnodeLayout.layoutableObject).frame = [subnodeLayout frame]; - } -} - - (void)displayWillStart { ASDisplayNodeAssertMainThread();