Working implementation of ASInterfaceState for Display and FetchData behaviors.

This commit is contained in:
Scott Goodson
2015-11-28 22:48:30 -08:00
parent 943cae7eb9
commit 1ed22866b1
4 changed files with 50 additions and 6 deletions

View File

@@ -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 */

View File

@@ -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();

View File

@@ -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

View File

@@ -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