diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 42c4bf79a9..ba941a9065 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -352,8 +352,9 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) - (void)__unloadNode { ASDisplayNodeAssertThreadAffinity(self); + ASDisplayNodeAssert([self isNodeLoaded], @"Implementation shouldn't call __unloadNode if not loaded: %@", self); ASDN::MutexLocker l(_propertyLock); - + if (_flags.layerBacked) _pendingViewState = [_ASPendingState pendingViewStateFromLayer:_layer]; else diff --git a/AsyncDisplayKit/Details/_ASDisplayView.mm b/AsyncDisplayKit/Details/_ASDisplayView.mm index 0d4e8c77ca..f542b29db6 100644 --- a/AsyncDisplayKit/Details/_ASDisplayView.mm +++ b/AsyncDisplayKit/Details/_ASDisplayView.mm @@ -151,8 +151,11 @@ needsSupernodeRemoval = YES; } } else { - // If supernode is loaded but our superview is nil, the user manually removed us, so disconnect supernode. - needsSupernodeRemoval = supernodeLoaded; + // If supernode is loaded but our superview is nil, the user likely manually removed us, so disconnect supernode. + // The unlikely alternative: we are in __unloadNode, with shouldRasterizeSubnodes just having been turned on. + // In the latter case, we don't want to disassemble the node hierarchy because all views are intentionally being destroyed. + BOOL nodeIsRasterized = ((_node.hierarchyState & ASHierarchyStateRasterized) == ASHierarchyStateRasterized); + needsSupernodeRemoval = (supernodeLoaded && !nodeIsRasterized); } if (needsSupernodeRemoval) { diff --git a/AsyncDisplayKit/Private/_ASPendingState.m b/AsyncDisplayKit/Private/_ASPendingState.m index 8d2c8f7665..37918e197b 100644 --- a/AsyncDisplayKit/Private/_ASPendingState.m +++ b/AsyncDisplayKit/Private/_ASPendingState.m @@ -798,8 +798,13 @@ static UIColor *defaultTintColor = nil; view.accessibilityIdentifier = accessibilityIdentifier; } +// FIXME: Make this more efficient by tracking which properties are set rather than reading everything. + (_ASPendingState *)pendingViewStateFromLayer:(CALayer *)layer { + if (!layer) { + return nil; + } + _ASPendingState *pendingState = [[_ASPendingState alloc] init]; pendingState.anchorPoint = layer.anchorPoint; @@ -877,8 +882,13 @@ static UIColor *defaultTintColor = nil; return pendingState; } +// FIXME: Make this more efficient by tracking which properties are set rather than reading everything. + (_ASPendingState *)pendingViewStateFromView:(UIView *)view { + if (!view) { + return nil; + } + _ASPendingState *pendingState = [[_ASPendingState alloc] init]; CALayer *layer = view.layer; diff --git a/examples/SocialAppLayout/Sample/ViewController.m b/examples/SocialAppLayout/Sample/ViewController.m index 1c089db9a3..ff6abbd3f8 100644 --- a/examples/SocialAppLayout/Sample/ViewController.m +++ b/examples/SocialAppLayout/Sample/ViewController.m @@ -134,4 +134,18 @@ return _socialAppDataSource.count; } +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + PostNode *postNode = (PostNode *)[_tableView nodeForRowAtIndexPath:indexPath]; + Post *post = _socialAppDataSource[indexPath.row]; + + BOOL shouldRasterize = postNode.shouldRasterizeDescendants; + shouldRasterize = !shouldRasterize; + postNode.shouldRasterizeDescendants = shouldRasterize; + + NSLog(@"%@ rasterization for %@'s post: %@", shouldRasterize ? @"Enabling" : @"Disabling", post.name, postNode); + + [tableView deselectRowAtIndexPath:indexPath animated:YES]; +} + @end