diff --git a/AsyncDisplayKit/ASDisplayNode+Beta.h b/AsyncDisplayKit/ASDisplayNode+Beta.h index 2642ba3f50..bad81b740a 100644 --- a/AsyncDisplayKit/ASDisplayNode+Beta.h +++ b/AsyncDisplayKit/ASDisplayNode+Beta.h @@ -39,6 +39,8 @@ /** @name Layout Transitioning */ +@property (nonatomic) BOOL usesImplicitHierarchyManagement; + /** * @discussion A place to perform your animation. New nodes have been inserted here. You can also use this time to re-order the hierarchy. */ diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 5a4e65fafc..48bcc15d7d 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -32,7 +32,7 @@ NSInteger const ASDefaultDrawingPriority = ASDefaultTransactionPriority; NSString * const ASRenderingEngineDidDisplayScheduledNodesNotification = @"ASRenderingEngineDidDisplayScheduledNodes"; NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp = @"ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp"; -@interface ASDisplayNode () +@interface ASDisplayNode () /** * @@ -54,12 +54,6 @@ NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp = @"AS #define TIME_SCOPED(outVar) #endif -@interface ASDisplayNode () <_ASDisplayLayerDelegate, _ASTransitionContextDelegate> - -@property (assign, nonatomic) BOOL implicitNodeHierarchyManagement; - -@end - @implementation ASDisplayNode // these dynamic properties all defined in ASLayoutOptionsPrivate.m @@ -611,7 +605,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize { return [self measureWithSizeRange:constrainedSize completion:^{ - if ([[self class] usesImplicitHierarchyManagement]) { + if (self.usesImplicitHierarchyManagement) { [self __implicitlyInsertSubnodes]; [self __implicitlyRemoveSubnodes]; } @@ -640,7 +634,9 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) _previousConstrainedSize = _constrainedSize; _constrainedSize = constrainedSize; - [self __calculateSubnodeOperationsWithLayout:_layout previousLayout:_previousLayout]; + if (self.usesImplicitHierarchyManagement) { + [self __calculateSubnodeOperations]; + } _flags.isMeasured = YES; completion(); @@ -657,32 +653,34 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) - (ASLayout *)transitionLayoutWithSizeRange:(ASSizeRange)constrainedSize animated:(BOOL)animated { + _usesImplicitHierarchyManagement = YES; // Temporary flag for 1.9.x return [self measureWithSizeRange:constrainedSize completion:^{ + _usesImplicitHierarchyManagement = NO; // Temporary flag for 1.9.x _transitionContext = [[_ASTransitionContext alloc] initWithAnimation:animated delegate:self]; [self __implicitlyInsertSubnodes]; [self animateLayoutTransition:_transitionContext]; }]; } -- (void)__calculateSubnodeOperationsWithLayout:(ASLayout *)layout previousLayout:(ASLayout *)previousLayout +- (void)__calculateSubnodeOperations { - if (previousLayout) { + if (_previousLayout) { NSIndexSet *insertions, *deletions; - [previousLayout.immediateSublayouts asdk_diffWithArray:layout.immediateSublayouts + [_previousLayout.immediateSublayouts asdk_diffWithArray:_layout.immediateSublayouts insertions:&insertions deletions:&deletions compareBlock:^BOOL(ASLayout *lhs, ASLayout *rhs) { return ASObjectIsEqual(lhs.layoutableObject, rhs.layoutableObject); }]; - filterNodesInLayoutAtIndexes(layout, insertions, &_insertedSubnodes, &_insertedSubnodePositions); - filterNodesInLayoutAtIndexesWithIntersectingNodes(previousLayout, + filterNodesInLayoutAtIndexes(_layout, insertions, &_insertedSubnodes, &_insertedSubnodePositions); + filterNodesInLayoutAtIndexesWithIntersectingNodes(_previousLayout, deletions, _insertedSubnodes, &_removedSubnodes, &_removedSubnodePositions); } else { - NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [layout.immediateSublayouts count])]; - filterNodesInLayoutAtIndexes(layout, indexes, &_insertedSubnodes, &_insertedSubnodePositions); + NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [_layout.immediateSublayouts count])]; + filterNodesInLayoutAtIndexes(_layout, indexes, &_insertedSubnodes, &_insertedSubnodePositions); _removedSubnodes = nil; } } @@ -768,6 +766,16 @@ static inline void filterNodesInLayoutAtIndexesWithIntersectingNodes( #pragma mark - Layout Transition +- (BOOL)usesImplicitHierarchyManagement +{ + return _usesImplicitHierarchyManagement ?: [[self class] usesImplicitHierarchyManagement]; +} + +- (void)setUsesImplicitHierarchyManagement:(BOOL)value +{ + _usesImplicitHierarchyManagement = value; +} + - (void)animateLayoutTransition:(id)context { [self __layoutSublayouts]; @@ -1820,7 +1828,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) layout = [ASLayout layoutWithLayoutableObject:self size:layout.size sublayouts:@[layout]]; } return [layout flattenedLayoutUsingPredicateBlock:^BOOL(ASLayout *evaluatedLayout) { - if ([[self class] usesImplicitHierarchyManagement]) { + if (self.usesImplicitHierarchyManagement) { return ASObjectIsEqual(layout, evaluatedLayout) == NO && [evaluatedLayout.layoutableObject isKindOfClass:[ASDisplayNode class]]; } else { return [_subnodes containsObject:evaluatedLayout.layoutableObject]; diff --git a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h index f243fdee79..70686f9819 100644 --- a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h +++ b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h @@ -72,6 +72,7 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo NSMutableArray *_subnodes; _ASTransitionContext *_transitionContext; + BOOL _usesImplicitHierarchyManagement; NSArray *_insertedSubnodes; NSArray *_removedSubnodes; diff --git a/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m b/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m index 0bb9fa327d..b54201dc8f 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m @@ -63,6 +63,15 @@ - (void)testFeatureFlag { XCTAssert([ASDisplayNode usesImplicitHierarchyManagement]); + ASDisplayNode *node = [[ASDisplayNode alloc] init]; + XCTAssert(node.usesImplicitHierarchyManagement); + + [ASDisplayNode setUsesImplicitHierarchyManagement:NO]; + XCTAssertFalse([ASDisplayNode usesImplicitHierarchyManagement]); + XCTAssertFalse(node.usesImplicitHierarchyManagement); + + node.usesImplicitHierarchyManagement = YES; + XCTAssert(node.usesImplicitHierarchyManagement); } - (void)testInitialNodeInsertionWithOrdering