From 1ed22866b1df811e939a68144842660b6d6f1ffd Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Sat, 28 Nov 2015 22:48:30 -0800 Subject: [PATCH] Working implementation of ASInterfaceState for Display and FetchData behaviors. --- AsyncDisplayKit/ASDisplayNode.h | 5 ++- AsyncDisplayKit/ASDisplayNode.mm | 40 +++++++++++++++++++ .../Details/ASRangeHandlerPreload.mm | 4 +- .../Details/ASRangeHandlerRender.mm | 7 ++-- 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index 51adccbc1c..45d23e07b8 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -181,7 +181,10 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState) */ @property (nonatomic, readonly, retain) CALayer *layer; -@property (nonatomic, readwrite) ASInterfaceState interfaceState; +@property (nonatomic, readonly) ASInterfaceState interfaceState; + +- (void)enterInterfaceState:(ASInterfaceState)interfaceState; +- (void)exitInterfaceState:(ASInterfaceState)interfaceState; /** @name Managing dimensions */ diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 4095552b77..8c639de1ba 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1729,6 +1729,46 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer) } } +- (void)enterInterfaceState:(ASInterfaceState)interfaceState +{ + recursivelyPerformBlockOnEveryNode(nil, self, ^(ASDisplayNode *node) { + node.interfaceState |= interfaceState; + }); +} + +- (void)exitInterfaceState:(ASInterfaceState)interfaceState +{ + recursivelyPerformBlockOnEveryNode(nil, self, ^(ASDisplayNode *node) { + node.interfaceState &= (!interfaceState); + }); +} + +void recursivelyPerformBlockOnEveryNode(CALayer *layer, ASDisplayNode *node, void(^performOnNode)(ASDisplayNode *node)) +{ + if (!node) { + ASDisplayNodeCAssertNotNil(layer, @"Cannot recursively perform with nil node and nil layer"); + ASDisplayNodeCAssertMainThread(); + node = [layer asyncdisplaykit_node]; + } + + if (node) { + performOnNode(node); + } + if (!layer && [node isNodeLoaded]) { + layer = node.layer; + } + + if (layer) { + for (CALayer *sublayer in [layer sublayers]) { + recursivelyPerformBlockOnEveryNode(sublayer, nil, performOnNode); + } + } else if (node) { + for (ASDisplayNode *subnode in [node subnodes]) { + recursivelyPerformBlockOnEveryNode(nil, subnode, performOnNode); + } + } +} + - (void)layout { ASDisplayNodeAssertMainThread(); diff --git a/AsyncDisplayKit/Details/ASRangeHandlerPreload.mm b/AsyncDisplayKit/Details/ASRangeHandlerPreload.mm index d30f6c1a40..fc61788fb0 100644 --- a/AsyncDisplayKit/Details/ASRangeHandlerPreload.mm +++ b/AsyncDisplayKit/Details/ASRangeHandlerPreload.mm @@ -16,13 +16,13 @@ - (void)node:(ASDisplayNode *)node enteredRangeOfType:(ASLayoutRangeType)rangeType { ASDisplayNodeAssert(rangeType == ASLayoutRangeTypePreload, @"Preload delegate should not handle other ranges"); - [node recursivelyFetchData]; + [node enterInterfaceState:ASInterfaceStateFetchData]; } - (void)node:(ASDisplayNode *)node exitedRangeOfType:(ASLayoutRangeType)rangeType { ASDisplayNodeAssert(rangeType == ASLayoutRangeTypePreload, @"Preload delegate should not handle other ranges"); - [node recursivelyClearFetchedData]; + [node exitInterfaceState:ASInterfaceStateFetchData]; } @end diff --git a/AsyncDisplayKit/Details/ASRangeHandlerRender.mm b/AsyncDisplayKit/Details/ASRangeHandlerRender.mm index e564564956..b2a751a8bd 100644 --- a/AsyncDisplayKit/Details/ASRangeHandlerRender.mm +++ b/AsyncDisplayKit/Details/ASRangeHandlerRender.mm @@ -57,7 +57,8 @@ [node.view removeFromSuperview]; } - [node recursivelySetDisplaySuspended:NO]; + // The node un-suspends display. + [node enterInterfaceState:ASInterfaceStateDisplay]; // Add the node's layer to an off-screen window to trigger display and mark its contents as non-volatile. // Use the layer directly to avoid the substantial overhead of UIView heirarchy manipulations. @@ -89,7 +90,8 @@ // preservation of this content could result in the app being killed, which is not likely preferable over briefly seeing placeholders in the event the user scrolls backwards. // Nonetheless, future changes to the implementation will likely eliminate this behavior to simplify debugging and extensibility of working range functionality. - [node recursivelySetDisplaySuspended:YES]; + // The node calls clearCurrentContents and suspends display + [node exitInterfaceState:ASInterfaceStateDisplay]; if (node.layer.superlayer != [[self workingWindow] layer]) { // In this case, the node has previously passed through the working range (or it is zero), and it has now fallen outside the working range. @@ -102,7 +104,6 @@ // At this point, the node's layer may validly be present either in the workingWindow, or in the contentsView of a cell. [node.layer removeFromSuperlayer]; - [node recursivelyClearContents]; } @end