From 11215bf97f31da460b488317f59f91c3ae765c0c Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Mon, 15 Aug 2016 12:06:06 -0700 Subject: [PATCH] [Automatic Hierarchy Management] Rename IHM to automatic hierarchy management and move out of beta header (#2066) * Rename automaticHierarchy to automaticallyManagesSubnodes * Comment adjustments --- AsyncDisplayKit/ASButtonNode.mm | 3 +- AsyncDisplayKit/ASCollectionView.mm | 1 - AsyncDisplayKit/ASDisplayNode+Beta.h | 5 -- AsyncDisplayKit/ASDisplayNode.h | 35 +++++++++- AsyncDisplayKit/ASDisplayNode.mm | 66 +++++++++---------- AsyncDisplayKit/ASTableView.mm | 1 - .../Private/ASDisplayNode+UIViewBridge.mm | 2 +- .../Private/ASDisplayNodeInternal.h | 2 +- .../Private/_ASHierarchyChangeSet.mm | 1 + .../ASDisplayNodeImplicitHierarchyTests.m | 27 +++----- 10 files changed, 77 insertions(+), 66 deletions(-) diff --git a/AsyncDisplayKit/ASButtonNode.mm b/AsyncDisplayKit/ASButtonNode.mm index f1f40a33cc..6341f13732 100644 --- a/AsyncDisplayKit/ASButtonNode.mm +++ b/AsyncDisplayKit/ASButtonNode.mm @@ -14,7 +14,6 @@ #import "ASDisplayNode+Subclasses.h" #import "ASBackgroundLayoutSpec.h" #import "ASInsetLayoutSpec.h" -#import "ASDisplayNode+Beta.h" #import "ASStaticLayoutSpec.h" @interface ASButtonNode () @@ -56,7 +55,7 @@ - (instancetype)init { if (self = [super init]) { - self.usesImplicitHierarchyManagement = YES; + self.automaticallyManagesSubnodes = YES; _contentSpacing = 8.0; _laysOutHorizontally = YES; diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index d7cd5b404c..dd12112668 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -18,7 +18,6 @@ #import "ASCollectionViewFlowLayoutInspector.h" #import "ASDisplayNodeExtras.h" #import "ASDisplayNode+FrameworkPrivate.h" -#import "ASDisplayNode+Beta.h" #import "ASInternalHelpers.h" #import "UICollectionViewLayout+ASConvenience.h" #import "ASRangeController.h" diff --git a/AsyncDisplayKit/ASDisplayNode+Beta.h b/AsyncDisplayKit/ASDisplayNode+Beta.h index aa3b3d96a1..9302b9cf2b 100644 --- a/AsyncDisplayKit/ASDisplayNode+Beta.h +++ b/AsyncDisplayKit/ASDisplayNode+Beta.h @@ -20,9 +20,6 @@ ASDISPLAYNODE_EXTERN_C_END @interface ASDisplayNode (Beta) -+ (BOOL)usesImplicitHierarchyManagement; -+ (void)setUsesImplicitHierarchyManagement:(BOOL)enabled; - /** * ASTableView and ASCollectionView now throw exceptions on invalid updates * like their UIKit counterparts. If YES, these classes will log messages @@ -63,8 +60,6 @@ ASDISPLAYNODE_EXTERN_C_END /** @name Layout Transitioning */ -@property (nonatomic) BOOL usesImplicitHierarchyManagement; - /** * @abstract Currently used by ASNetworkImageNode and ASMultiplexImageNode to allow their placeholders to stay if they are loading an image from the network. * Otherwise, a display pass is scheduled and completes, but does not actually draw anything - and ASDisplayNode considers the element finished. diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index 3e2a227b01..cd4f550835 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -813,8 +813,24 @@ NS_ASSUME_NONNULL_BEGIN @end /* - ASDisplayNode participates in ASAsyncTransactions, so you can determine when your subnodes are done rendering. - See: -(void)asyncdisplaykit_asyncTransactionContainerStateDidChange in ASDisplayNodeSubclass.h + * ASDisplayNode support for automatic subnode management. + */ +@interface ASDisplayNode (AutomaticSubnodeManagement) + +/** + * @abstract A boolean that shows whether the node automatically inserts and removes nodes based on the presence or + * absence of the node and its subnodes is completely determined in its layoutSpecThatFits: method. + * + * @discussion If flag is YES the node no longer require addSubnode: or removeFromSupernode method calls. The presence + * or absence of subnodes is completely determined in its layoutSpecThatFits: method. + */ +@property (nonatomic, assign) BOOL automaticallyManagesSubnodes; + +@end + +/* + * ASDisplayNode participates in ASAsyncTransactions, so you can determine when your subnodes are done rendering. + * See: -(void)asyncdisplaykit_asyncTransactionContainerStateDidChange in ASDisplayNodeSubclass.h */ @interface ASDisplayNode (ASDisplayNodeAsyncTransactionContainer) @end @@ -829,7 +845,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)addSubnode:(nonnull ASDisplayNode *)node; @end -/** CALayer(AsyncDisplayKit) defines convenience method for adding sub-ASDisplayNode to a CALayer. */ +/* + * CALayer(AsyncDisplayKit) defines convenience method for adding sub-ASDisplayNode to a CALayer. + */ @interface CALayer (AsyncDisplayKit) /** * Convenience method, equivalent to [layer addSublayer:node.layer]. @@ -890,6 +908,17 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)cancelLayoutTransitionsInProgress ASDISPLAYNODE_DEPRECATED; +/** + * @abstract A boolean that shows whether the node automatically inserts and removes nodes based on the presence or + * absence of the node and its subnodes is completely determined in its layoutSpecThatFits: method. + * + * @discussion If flag is YES the node no longer require addSubnode: or removeFromSupernode method calls. The presence + * or absence of subnodes is completely determined in its layoutSpecThatFits: method. + * + * @deprecated Deprecated in version 2.0: Use automaticallyManagesSubnodes + */ +@property (nonatomic, assign) BOOL usesImplicitHierarchyManagement ASDISPLAYNODE_DEPRECATED; + - (void)reclaimMemory ASDISPLAYNODE_DEPRECATED; - (void)recursivelyReclaimMemory ASDISPLAYNODE_DEPRECATED; @property (nonatomic, assign) BOOL placeholderFadesOut ASDISPLAYNODE_DEPRECATED; diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 3120d82549..fbcf0396d8 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -77,18 +77,6 @@ NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp = @"AS @synthesize isFinalLayoutable = _isFinalLayoutable; @synthesize threadSafeBounds = _threadSafeBounds; -static BOOL usesImplicitHierarchyManagement = NO; - -+ (BOOL)usesImplicitHierarchyManagement -{ - return usesImplicitHierarchyManagement; -} - -+ (void)setUsesImplicitHierarchyManagement:(BOOL)enabled -{ - usesImplicitHierarchyManagement = enabled; -} - static BOOL suppressesInvalidCollectionUpdateExceptions = YES; + (BOOL)suppressesInvalidCollectionUpdateExceptions @@ -703,6 +691,20 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) return !self.isNodeLoaded; } +#pragma mark - Automatic Hierarchy + +- (BOOL)automaticallyManagesSubnodes +{ + ASDN::MutexLocker l(__instanceLock__); + return _automaticallyManagesSubnodes; +} + +- (void)setAutomaticallyManagesSubnodes:(BOOL)automaticallyManagesSubnodes +{ + ASDN::MutexLocker l(__instanceLock__); + _automaticallyManagesSubnodes = automaticallyManagesSubnodes; +} + #pragma mark - Layout Transition - (void)transitionLayoutAnimated:(BOOL)animated measurementCompletion:(void (^)())completion @@ -751,11 +753,11 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) ASLayoutableSetCurrentContext(ASLayoutableContextMake(transitionID, NO)); ASDN::MutexLocker l(__instanceLock__); - BOOL disableImplicitHierarchyManagement = self.usesImplicitHierarchyManagement == NO; - self.usesImplicitHierarchyManagement = YES; // Temporary flag for 1.9.x + BOOL automaticallyManagesSubnodesDisabled = (self.automaticallyManagesSubnodes == NO); + self.automaticallyManagesSubnodes = YES; // Temporary flag for 1.9.x newLayout = [self calculateLayoutThatFits:constrainedSize]; - if (disableImplicitHierarchyManagement) { - self.usesImplicitHierarchyManagement = NO; // Temporary flag for 1.9.x + if (automaticallyManagesSubnodesDisabled) { + self.automaticallyManagesSubnodes = NO; // Temporary flag for 1.9.x } ASLayoutableClearCurrentContext(); @@ -820,18 +822,6 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) } } -- (BOOL)usesImplicitHierarchyManagement -{ - ASDN::MutexLocker l(__instanceLock__); - return _usesImplicitHierarchyManagement ? : [[self class] usesImplicitHierarchyManagement]; -} - -- (void)setUsesImplicitHierarchyManagement:(BOOL)value -{ - ASDN::MutexLocker l(__instanceLock__); - _usesImplicitHierarchyManagement = value; -} - - (BOOL)_isTransitionInProgress { ASDN::MutexLocker l(__instanceLock__); @@ -1019,8 +1009,8 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) */ - (void)_completeLayoutTransition:(ASLayoutTransition *)layoutTransition { - // Layout transition is not supported for non implicit hierarchy managed nodes yet - if (layoutTransition == nil || self.usesImplicitHierarchyManagement == NO) { + // Layout transition is not supported for nodes that are not have automatic subnode management enabled + if (layoutTransition == nil || self.automaticallyManagesSubnodes == NO) { return; } @@ -1186,7 +1176,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) ASDN::MutexLocker l(__instanceLock__); // FIXME: Ideally we'd call this as soon as the node receives -setNeedsLayout - // but implicit hierarchy management would require us to modify the node tree + // but automatic subnode management would require us to modify the node tree // in the background on a loaded node, which isn't currently supported. if (_pendingViewState.hasSetNeedsLayout) { [self __setNeedsLayout]; @@ -1982,7 +1972,7 @@ static NSInteger incrementIfFound(NSInteger i) { // If a node was added to a supernode, the supernode could be in a layout pending state. All of the hierarchy state // properties related to the transition need to be copied over as well as propagated down the subtree. - // This is especially important as with Implicit Hierarchy Management adding subnodes can happen while a transition + // This is especially important as with automatic subnode management, adding subnodes can happen while a transition // is in fly if (ASHierarchyStateIncludesLayoutPending(stateToEnterOrExit)) { int32_t pendingTransitionId = newSupernode.pendingTransitionID; @@ -2701,7 +2691,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) ASDisplayNodeAssertTrue(layout.size.width >= 0.0); ASDisplayNodeAssertTrue(layout.size.height >= 0.0); - if (layoutTransition == nil || self.usesImplicitHierarchyManagement == NO) { + if (layoutTransition == nil || self.automaticallyManagesSubnodes == NO) { return; } @@ -3294,6 +3284,16 @@ static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode"; [self cancelLayoutTransition]; } +- (BOOL)usesImplicitHierarchyManagement +{ + return self.automaticallyManagesSubnodes; +} + +- (void)setUsesImplicitHierarchyManagement:(BOOL)enabled +{ + self.automaticallyManagesSubnodes = enabled; +} + - (void)setPlaceholderFadesOut:(BOOL)placeholderFadesOut { self.placeholderFadeDuration = placeholderFadesOut ? 0.1 : 0.0; diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 85d24d199d..079ca9e241 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -17,7 +17,6 @@ #import "ASChangeSetDataController.h" #import "ASDelegateProxy.h" #import "ASDisplayNodeExtras.h" -#import "ASDisplayNode+Beta.h" #import "ASDisplayNode+FrameworkPrivate.h" #import "ASInternalHelpers.h" #import "ASLayout.h" diff --git a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm index 38901bce61..324fb875ac 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm +++ b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm @@ -344,7 +344,7 @@ if (shouldApply) { _layer.layerProperty = (layerValueExpr); } else { ASDisplayNo // The node is loaded but we're not on main. // We will call [self __setNeedsLayout] when we apply // the pending state. We need to call it on main if the node is loaded - // to support implicit hierarchy management. + // to support automatic subnode management. [ASDisplayNodeGetPendingState(self) setNeedsLayout]; } else { // The node is not loaded and we're not on main. diff --git a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h index 9f429e6717..f3528bbfe4 100644 --- a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h +++ b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h @@ -124,7 +124,7 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo // Main thread only _ASTransitionContext *_pendingLayoutTransitionContext; - BOOL _usesImplicitHierarchyManagement; + BOOL _automaticallyManagesSubnodes; NSTimeInterval _defaultLayoutTransitionDuration; NSTimeInterval _defaultLayoutTransitionDelay; UIViewAnimationOptions _defaultLayoutTransitionOptions; diff --git a/AsyncDisplayKit/Private/_ASHierarchyChangeSet.mm b/AsyncDisplayKit/Private/_ASHierarchyChangeSet.mm index 2b080cece7..649f39e8c3 100644 --- a/AsyncDisplayKit/Private/_ASHierarchyChangeSet.mm +++ b/AsyncDisplayKit/Private/_ASHierarchyChangeSet.mm @@ -15,6 +15,7 @@ #import "NSIndexSet+ASHelpers.h" #import "ASAssert.h" #import "ASDisplayNode+Beta.h" + #import #define ASFailUpdateValidation(...)\ diff --git a/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m b/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m index 28748af28a..6ce6312aeb 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m @@ -47,28 +47,13 @@ @implementation ASDisplayNodeImplicitHierarchyTests -- (void)setUp { - [super setUp]; - [ASDisplayNode setUsesImplicitHierarchyManagement:YES]; -} - -- (void)tearDown { - [ASDisplayNode setUsesImplicitHierarchyManagement:NO]; - [super tearDown]; -} - - (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); + XCTAssertFalse(node.automaticallyManagesSubnodes); + + node.automaticallyManagesSubnodes = YES; + XCTAssertTrue(node.automaticallyManagesSubnodes); } - (void)testInitialNodeInsertionWithOrdering @@ -80,6 +65,7 @@ ASDisplayNode *node5 = [[ASDisplayNode alloc] init]; ASSpecTestDisplayNode *node = [[ASSpecTestDisplayNode alloc] init]; + node.automaticallyManagesSubnodes = YES; node.layoutSpecBlock = ^(ASDisplayNode *weakNode, ASSizeRange constrainedSize) { ASStaticLayoutSpec *staticLayout = [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[node4]]; @@ -106,6 +92,7 @@ ASDisplayNode *node3 = [[ASDisplayNode alloc] init]; ASSpecTestDisplayNode *node = [[ASSpecTestDisplayNode alloc] init]; + node.automaticallyManagesSubnodes = YES; node.layoutSpecBlock = ^(ASDisplayNode *weakNode, ASSizeRange constrainedSize){ ASSpecTestDisplayNode *strongNode = (ASSpecTestDisplayNode *)weakNode; if ([strongNode.layoutState isEqualToNumber:@1]) { @@ -136,6 +123,7 @@ ASDisplayNode *node2 = [[ASDisplayNode alloc] init]; ASSpecTestDisplayNode *node = [[ASSpecTestDisplayNode alloc] init]; + node.automaticallyManagesSubnodes = YES; node.layoutSpecBlock = ^(ASDisplayNode *weakNode, ASSizeRange constrainedSize) { ASSpecTestDisplayNode *strongNode = (ASSpecTestDisplayNode *)weakNode; if ([strongNode.layoutState isEqualToNumber:@1]) { @@ -179,6 +167,7 @@ ASDisplayNode *node2 = [[ASDisplayNode alloc] init]; ASSpecTestDisplayNode *node = [[ASSpecTestDisplayNode alloc] init]; + node.automaticallyManagesSubnodes = YES; node.layoutSpecBlock = ^(ASDisplayNode *weakNode, ASSizeRange constrainedSize) { ASSpecTestDisplayNode *strongNode = (ASSpecTestDisplayNode *)weakNode;