diff --git a/AsyncDisplayKit/ASCellNode.m b/AsyncDisplayKit/ASCellNode.m index ef6652b700..dbd11e0523 100644 --- a/AsyncDisplayKit/ASCellNode.m +++ b/AsyncDisplayKit/ASCellNode.m @@ -62,6 +62,29 @@ } } +- (void)clearFetchedData +{ + [super clearFetchedData]; + NSLog(@"%p - clearFetchedData", self); +} + +- (void)fetchData +{ + [super fetchData]; + NSLog(@"%p - fetchData", self); +} + +- (void)clearContents +{ + [super clearContents]; + NSLog(@"%p - clearContents", self); +} + +- (void)dealloc +{ + NSLog(@"%p - dealloc", self); +} + - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { ASDisplayNodeAssertMainThread(); diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 9c52f08c21..f70d336b88 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -665,7 +665,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) [self _addSubnodeViewsAndLayers]; } - [self recursivelyDisplayImmediately]; + [self recursivelyEnsureDisplay]; } } @@ -1454,8 +1454,8 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer) - (void)recursivelyEnsureDisplay { ASDisplayNodeAssertMainThread(); - ASDisplayNodeAssert(self.isNodeLoaded, @"Node must have layer or view loaded to use -recursivelyEnsureDisplay"); - ASDisplayNodeAssert(self.inHierarchy && (self.isLayerBacked || self.view.window != nil), @"Node must be in a hierarchy to use -recursivelyEnsureDisplay"); +// ASDisplayNodeAssert(self.isNodeLoaded, @"Node must have layer or view loaded to use -recursivelyEnsureDisplay"); +// ASDisplayNodeAssert(self.inHierarchy && (self.isLayerBacked || self.view.window != nil), @"Node must be in a hierarchy to use -recursivelyEnsureDisplay"); CALayer *layer = self.layer; // -layoutIfNeeded is recursive, and even walks up to superlayers to check if they need layout, diff --git a/AsyncDisplayKit/Details/ASRangeHandlerRender.mm b/AsyncDisplayKit/Details/ASRangeHandlerRender.mm index b2a751a8bd..ee320d7e32 100644 --- a/AsyncDisplayKit/Details/ASRangeHandlerRender.mm +++ b/AsyncDisplayKit/Details/ASRangeHandlerRender.mm @@ -12,13 +12,16 @@ #import "ASDisplayNode+Subclasses.h" #import "ASDisplayNodeInternal.h" +#define USE_WORKING_WINDOW 0 + @interface ASRangeHandlerRender () @property (nonatomic,readonly) UIWindow *workingWindow; @end @implementation ASRangeHandlerRender -@synthesize workingWindow = _workingWindow; +#if USE_WORKING_WINDOW +@synthesize workingWindow = _workingWindow; - (UIWindow *)workingWindow { ASDisplayNodeAssertMainThread(); @@ -45,6 +48,7 @@ [self node:node exitedRangeOfType:ASLayoutRangeTypeRender]; } } +#endif - (void)node:(ASDisplayNode *)node enteredRangeOfType:(ASLayoutRangeType)rangeType { @@ -60,12 +64,17 @@ // The node un-suspends display. [node enterInterfaceState:ASInterfaceStateDisplay]; + +#if USE_WORKING_WINDOW // 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. // Any view-backed nodes will still create their views in order to assemble the layer heirarchy, and they will // also assemble a view subtree for the node, but we avoid the much more significant expense triggered by a view // being added or removed from an onscreen window (responder chain setup, will/DidMoveToWindow: recursive calls, etc) [[[self workingWindow] layer] addSublayer:node.layer]; +#else + [node recursivelyEnsureDisplay]; // Need to do this without waiting +#endif } - (void)node:(ASDisplayNode *)node exitedRangeOfType:(ASLayoutRangeType)rangeType @@ -93,6 +102,7 @@ // The node calls clearCurrentContents and suspends display [node exitInterfaceState:ASInterfaceStateDisplay]; +#if USE_WORKING_WINDOW 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. if (![node isLayerBacked]) { @@ -104,6 +114,13 @@ // 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]; +#else + if (![node isLayerBacked]) { + [node.view removeFromSuperview]; + } else { + [node.layer removeFromSuperlayer]; + } +#endif } @end diff --git a/AsyncDisplayKit/Details/_ASDisplayLayer.mm b/AsyncDisplayKit/Details/_ASDisplayLayer.mm index 99e4bf68e8..b69d935677 100644 --- a/AsyncDisplayKit/Details/_ASDisplayLayer.mm +++ b/AsyncDisplayKit/Details/_ASDisplayLayer.mm @@ -146,11 +146,9 @@ - (void)displayImmediately { - // REVIEW: Should this respect isDisplaySuspended? If so, we'd probably want to synchronously display when - // setDisplaySuspended:No is called, rather than just scheduling. The thread affinity for the displayImmediately - // call will be tricky if we need to support this, though. It probably should just execute if displayImmediately is - // called directly. The caller should be responsible for not calling displayImmediately if it wants to obey the - // suspended state. + // This method is a low-level bypass that avoids touching CA, including any reset of the + // needsDisplay flag, until the .contents property is set with the result. + // It is designed to be able to block the thread of any caller and fully execute the display. ASDisplayNodeAssertMainThread(); [self display:NO]; diff --git a/AsyncDisplayKit/Layout/ASAsciiArtBoxCreator.m b/AsyncDisplayKit/Layout/ASAsciiArtBoxCreator.m index 9aa3bd8fdb..5f57b5aa86 100644 --- a/AsyncDisplayKit/Layout/ASAsciiArtBoxCreator.m +++ b/AsyncDisplayKit/Layout/ASAsciiArtBoxCreator.m @@ -111,7 +111,7 @@ typedef NS_ENUM(NSUInteger, PIDebugBoxPaddingLocation) [paddedLines addObject:paddedLine]; } concatenatedLines = paddedLines; - totalLineLength += difference; + // totalLineLength += difference; } concatenatedLines = [self appendTopAndBottomToBoxString:concatenatedLines parent:parent]; return [concatenatedLines componentsJoinedByString:@"\n"]; diff --git a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm index 28a35a1c22..65ad2a63e6 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm +++ b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm @@ -223,6 +223,14 @@ [rasterizedContainerNode setNeedsDisplay]; } else { [_layer setNeedsDisplay]; + + if (_layer && !self.isSynchronous && self.displaysAsynchronously) { + // It's essenital that any layout pass that is scheduled during the current + // runloop has a chance to be applied / scheduled. + dispatch_async(dispatch_get_main_queue(), ^{ + [self recursivelyEnsureDisplay]; + }); + } } }