Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Commit 16b0bd9

Browse files
committed
Merge pull request #957 from facebook/HierarchyAndInterfaceStateSync
Ensure that .hierarchyState is propogated to new subnodes early enough for us to reference it as the views are added.
2 parents 834cf79 + 32a99e3 commit 16b0bd9

1 file changed

Lines changed: 20 additions & 5 deletions

File tree

AsyncDisplayKit/ASDisplayNode.mm

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,10 @@ - (void)addSubnode:(ASDisplayNode *)subnode
950950
_subnodes = [[NSMutableArray alloc] init];
951951

952952
[_subnodes addObject:subnode];
953+
954+
// This call will apply our .hierarchyState to the new subnode.
955+
// If we are a managed hierarchy, as in ASCellNode trees, it will also apply our .interfaceState.
956+
[subnode __setSupernode:self];
953957

954958
if (self.nodeLoaded) {
955959
// If this node has a view or layer, force the subnode to also create its view or layer and add it to the hierarchy here.
@@ -969,8 +973,6 @@ - (void)addSubnode:(ASDisplayNode *)subnode
969973
if (isMovingEquivalentParents) {
970974
[subnode __decrementVisibilityNotificationsDisabled];
971975
}
972-
973-
[subnode __setSupernode:self];
974976
}
975977

976978
/*
@@ -1267,7 +1269,7 @@ - (void)__decrementVisibilityNotificationsDisabled
12671269
}
12681270

12691271
// This uses the layer hieararchy for safety. Who knows what people might do and it would be bad to have visibilty out of sync
1270-
- (BOOL)__hasParentWithVisibilityNotificationsDisabled
1272+
- (BOOL)__selfOrParentHasVisibilityNotificationsDisabled
12711273
{
12721274
CALayer *layer = _layer;
12731275
do {
@@ -1287,7 +1289,7 @@ - (void)__enterHierarchy
12871289
{
12881290
ASDisplayNodeAssertMainThread();
12891291
ASDisplayNodeAssert(!_flags.isEnteringHierarchy, @"Should not cause recursive __enterHierarchy");
1290-
if (!self.inHierarchy && !_flags.visibilityNotificationsDisabled && ![self __hasParentWithVisibilityNotificationsDisabled]) {
1292+
if (!self.inHierarchy && !_flags.visibilityNotificationsDisabled && ![self __selfOrParentHasVisibilityNotificationsDisabled]) {
12911293
self.inHierarchy = YES;
12921294
_flags.isEnteringHierarchy = YES;
12931295
if (self.shouldRasterizeDescendants) {
@@ -1309,7 +1311,7 @@ - (void)__exitHierarchy
13091311
{
13101312
ASDisplayNodeAssertMainThread();
13111313
ASDisplayNodeAssert(!_flags.isExitingHierarchy, @"Should not cause recursive __exitHierarchy");
1312-
if (self.inHierarchy && !_flags.visibilityNotificationsDisabled && ![self __hasParentWithVisibilityNotificationsDisabled]) {
1314+
if (self.inHierarchy && !_flags.visibilityNotificationsDisabled && ![self __selfOrParentHasVisibilityNotificationsDisabled]) {
13131315
self.inHierarchy = NO;
13141316

13151317
[self.asyncLayer cancelAsyncDisplay];
@@ -1807,6 +1809,19 @@ - (void)setHierarchyState:(ASHierarchyState)newState
18071809
_hierarchyState = newState;
18081810
}
18091811

1812+
// Entered or exited contents rendering state.
1813+
if ((newState & ASHierarchyStateRangeManaged) != (oldState & ASHierarchyStateRangeManaged)) {
1814+
if (newState & ASHierarchyStateRangeManaged) {
1815+
[self enterInterfaceState:self.supernode.interfaceState];
1816+
} else {
1817+
// The case of exiting a range-managed state should be fairly rare. Adding or removing the node
1818+
// to a view hierarchy will cause its interfaceState to be either fully set or unset (all fields),
1819+
// but because we might be about to be added to a view hierarchy, exiting the interface state now
1820+
// would cause inefficient churn. The tradeoff is that we may not clear contents / fetched data
1821+
// for nodes that are removed from a managed state and then retained but not used (bad idea anyway!)
1822+
}
1823+
}
1824+
18101825
if (newState != oldState) {
18111826
LOG(@"setHierarchyState: oldState = %lu, newState = %lu", (unsigned long)oldState, (unsigned long)newState);
18121827
}

0 commit comments

Comments
 (0)