From a30c087616b8a57a802bc63b01368654656a53e5 Mon Sep 17 00:00:00 2001 From: Nadine Salter Date: Tue, 2 Dec 2014 16:53:02 -0800 Subject: [PATCH 1/3] Clean up ASDisplayNode internal flags. * Reorganise and rename `_flags` for clarity and consistency. * Remove ambiguity between `implementsDisplay` and `hasClassDisplay`. * Delete useless `hasWillDisplayAsyncLayer` check -- make it a simple subclass override point, as with `didDisplayAsyncLayer:`. * Minor comment cleanup. --- AsyncDisplayKit/ASDisplayNode.h | 4 +- AsyncDisplayKit/ASDisplayNode.mm | 107 +++++++++--------- .../Private/ASDisplayNode+AsyncDisplay.mm | 10 +- .../Private/ASDisplayNode+UIViewBridge.mm | 14 +-- .../Private/ASDisplayNodeInternal.h | 35 +++--- 5 files changed, 87 insertions(+), 83 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index e2070e3202..c8b20a0e07 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -74,7 +74,7 @@ /** - * @abstract Returns whether the view is synchronous. + * @abstract Returns whether the node is synchronous. * * @return NO if the node wraps a _ASDisplayView, YES otherwise. */ @@ -98,7 +98,7 @@ /** * @abstract Returns whether a node's backing view or layer is loaded. * - * @return YES if a view is loaded, or if isLayerBacked is YES and layer is not nil; NO otherwise. + * @return YES if a view is loaded, or if layerBacked is YES and layer is not nil; NO otherwise. */ @property (atomic, readonly, assign, getter=isNodeLoaded) BOOL nodeLoaded; diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index be0915e9f6..8e056e7168 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -103,22 +103,19 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) #pragma mark - Lifecycle -// Avoid recursive loops if a subclass implements an init method that calls -initWith*Class: - (void)_initializeInstance { _contentsScaleForDisplay = ASDisplayNodeScreenScale(); _displaySentinel = [[ASSentinel alloc] init]; - _flags.inWindow = NO; + _flags.isInWindow = NO; _flags.displaysAsynchronously = YES; // As an optimization, it may be worth a caching system that performs these checks once per class in +initialize (see above). - _flags.implementsDisplay = [[self class] respondsToSelector:@selector(drawRect:withParameters:isCancelled:isRasterizing:)] || [self.class respondsToSelector:@selector(displayWithParameters:isCancelled:)]; - - _flags.hasClassDisplay = ([[self class] respondsToSelector:@selector(displayWithParameters:isCancelled:)] ? 1 : 0); - _flags.hasWillDisplayAsyncLayer = ([self respondsToSelector:@selector(willDisplayAsyncLayer:)] ? 1 : 0); - _flags.hasDrawParametersForAsyncLayer = ([self respondsToSelector:@selector(drawParametersForAsyncLayer:)] ? 1 : 0); + _flags.implementsDrawRect = ([[self class] respondsToSelector:@selector(drawRect:withParameters:isCancelled:isRasterizing:)] ? 1 : 0); + _flags.implementsImageDisplay = ([[self class] respondsToSelector:@selector(displayWithParameters:isCancelled:)] ? 1 : 0); + _flags.implementsDrawParameters = ([self respondsToSelector:@selector(drawParametersForAsyncLayer:)] ? 1 : 0); } - (id)init @@ -140,7 +137,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) [self _initializeInstance]; _viewClass = viewClass; - _flags.isSynchronous = ![viewClass isSubclassOfClass:[_ASDisplayView class]]; + _flags.synchronous = ![viewClass isSubclassOfClass:[_ASDisplayView class]]; return self; } @@ -154,8 +151,8 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) [self _initializeInstance]; _layerClass = layerClass; - _flags.isSynchronous = ![layerClass isSubclassOfClass:[_ASDisplayLayer class]]; - _flags.isLayerBacked = YES; + _flags.synchronous = ![layerClass isSubclassOfClass:[_ASDisplayLayer class]]; + _flags.layerBacked = YES; return self; } @@ -178,7 +175,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) _view = nil; _subnodes = nil; - if (_flags.isLayerBacked) + if (_flags.layerBacked) _layer.delegate = nil; _layer = nil; @@ -277,8 +274,8 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) - (UIView *)view { - ASDisplayNodeAssert(!_flags.isLayerBacked, @"Call to -view undefined on layer-backed nodes"); - if (_flags.isLayerBacked) { + ASDisplayNodeAssert(!_flags.layerBacked, @"Call to -view undefined on layer-backed nodes"); + if (_flags.layerBacked) { return nil; } if (!_view) { @@ -293,7 +290,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) if (!_layer) { ASDisplayNodeAssertMainThread(); - if (!_flags.isLayerBacked) { + if (!_flags.layerBacked) { return self.view.layer; } [self _loadViewOrLayerIsLayerBacked:YES]; @@ -304,10 +301,10 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) // Returns nil if our view is not an _ASDisplayView, but will create it if necessary. - (_ASDisplayView *)ensureAsyncView { - return _flags.isSynchronous ? nil:(_ASDisplayView *)self.view; + return _flags.synchronous ? nil : (_ASDisplayView *)self.view; } -// Returns nil if the layer is not an _ASDisplayLayer; will not create the view if nil +// Returns nil if the layer is not an _ASDisplayLayer; will not create the layer if nil. - (_ASDisplayLayer *)asyncLayer { ASDN::MutexLocker l(_propertyLock); @@ -317,17 +314,17 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) - (BOOL)isNodeLoaded { ASDN::MutexLocker l(_propertyLock); - return (_view != nil || (_flags.isLayerBacked && _layer != nil)); + return (_view != nil || (_flags.layerBacked && _layer != nil)); } - (BOOL)isSynchronous { - return _flags.isSynchronous; + return _flags.synchronous; } - (void)setSynchronous:(BOOL)flag { - _flags.isSynchronous = flag; + _flags.synchronous = flag; } - (void)setLayerBacked:(BOOL)isLayerBacked @@ -336,15 +333,15 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) ASDN::MutexLocker l(_propertyLock); ASDisplayNodeAssert(!_view && !_layer, @"Cannot change isLayerBacked after layer or view has loaded"); - if (isLayerBacked != _flags.isLayerBacked && !_view && !_layer) { - _flags.isLayerBacked = isLayerBacked; + if (isLayerBacked != _flags.layerBacked && !_view && !_layer) { + _flags.layerBacked = isLayerBacked; } } - (BOOL)isLayerBacked { ASDN::MutexLocker l(_propertyLock); - return _flags.isLayerBacked; + return _flags.layerBacked; } #pragma mark - @@ -360,10 +357,10 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) // - we haven't already // - the width is different from the last time // - the height is different from the last time - if (!_flags.sizeCalculated || !CGSizeEqualToSize(constrainedSize, _constrainedSize)) { + if (!_flags.isMeasured || !CGSizeEqualToSize(constrainedSize, _constrainedSize)) { _size = [self calculateSizeThatFits:constrainedSize]; _constrainedSize = constrainedSize; - _flags.sizeCalculated = YES; + _flags.isMeasured = YES; } ASDisplayNodeAssertTrue(_size.width >= 0.0); @@ -387,7 +384,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) ASDisplayNodeAssertThreadAffinity(self); // Can't do this for synchronous nodes (using layers that are not _ASDisplayLayer and so we can't control display prevention/cancel) - if (_flags.isSynchronous) + if (_flags.synchronous) return; ASDN::MutexLocker l(_propertyLock); @@ -467,7 +464,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) - (void)displayImmediately { ASDisplayNodeAssertMainThread(); - ASDisplayNodeAssert(!_flags.isSynchronous, @"this method is designed for asynchronous mode only"); + ASDisplayNodeAssert(!_flags.synchronous, @"this method is designed for asynchronous mode only"); [[self asyncLayer] displayImmediately]; } @@ -631,6 +628,10 @@ static inline CATransform3D _calculateTransformFromReferenceToTarget(ASDisplayNo #pragma mark - _ASDisplayLayerDelegate +- (void)willDisplayAsyncLayer:(_ASDisplayLayer *)layer +{ +} + - (void)didDisplayAsyncLayer:(_ASDisplayLayer *)layer { // Subclass hook. @@ -648,7 +649,7 @@ static inline CATransform3D _calculateTransformFromReferenceToTarget(ASDisplayNo [self __exitHierarchy]; } - ASDisplayNodeAssert(_flags.isLayerBacked, @"We shouldn't get called back here if there is no layer"); + ASDisplayNodeAssert(_flags.layerBacked, @"We shouldn't get called back here if there is no layer"); return (id)[NSNull null]; } @@ -657,9 +658,9 @@ static inline CATransform3D _calculateTransformFromReferenceToTarget(ASDisplayNo static bool disableNotificationsForMovingBetweenParents(ASDisplayNode *from, ASDisplayNode *to) { if (!from || !to) return NO; - if (from->_flags.isSynchronous) return NO; - if (to->_flags.isSynchronous) return NO; - if (from->_flags.inWindow != to->_flags.inWindow) return NO; + if (from->_flags.synchronous) return NO; + if (to->_flags.synchronous) return NO; + if (from->_flags.isInWindow != to->_flags.isInWindow) return NO; return YES; } @@ -960,14 +961,14 @@ static NSInteger incrementIfFound(NSInteger i) { [_supernode _removeSubnode:self]; if (ASDisplayNodeThreadIsMain()) { - if (_flags.isLayerBacked) { + if (_flags.layerBacked) { [_layer removeFromSuperlayer]; } else { [_view removeFromSuperview]; } } else { dispatch_async(dispatch_get_main_queue(), ^{ - if (_flags.isLayerBacked) { + if (_flags.layerBacked) { [_layer removeFromSuperlayer]; } else { [_view removeFromSuperview]; @@ -985,7 +986,7 @@ static NSInteger incrementIfFound(NSInteger i) { - (void)__incrementVisibilityNotificationsDisabled { ASDN::MutexLocker l(_propertyLock); - const size_t maxVisibilityIncrement = (1ULL< { @protected - ASDN::RecursiveMutex _propertyLock; // Protects access to the _view, _pendingViewState, _subnodes, _supernode, _renderingSubnodes, and other properties which are accessed from multiple threads. + // Protects access to _view, _layer, _pendingViewState, _subnodes, _supernode, and other properties which are accessed from multiple threads. + ASDN::RecursiveMutex _propertyLock; ASDisplayNode * __weak _supernode; @@ -55,20 +56,24 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()); _ASPendingState *_pendingViewState; struct { - unsigned implementsDisplay:1; - unsigned isSynchronous:1; - unsigned isLayerBacked:1; - unsigned sizeCalculated:1; - unsigned preventOrCancelDisplay:1; + // public properties + unsigned synchronous:1; + unsigned layerBacked:1; unsigned displaysAsynchronously:1; unsigned shouldRasterizeDescendants:1; - unsigned visibilityNotificationsDisabled:visibilityNotificationsDisabledBits; - unsigned isInEnterHierarchy:1; - unsigned isInExitHierarchy:1; - unsigned inWindow:1; - unsigned hasWillDisplayAsyncLayer:1; - unsigned hasDrawParametersForAsyncLayer:1; - unsigned hasClassDisplay:1; + unsigned preventOrCancelDisplay:1; + + // whether custom drawing is enabled + unsigned implementsDrawRect:1; + unsigned implementsImageDisplay:1; + unsigned implementsDrawParameters:1; + + // internal state + unsigned isMeasured:1; + unsigned isEnteringHierarchy:1; + unsigned isExitingHierarchy:1; + unsigned isInWindow:1; + unsigned visibilityNotificationsDisabled:VISIBILITY_NOTIFICATIONS_DISABLED_BITS; } _flags; ASDisplayNodeExtraIvars _extra; @@ -100,7 +105,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()); // The visibility state of the node. Changed before calling willAppear, willDisappear, and didDisappear. @property (nonatomic, readwrite, assign, getter = isInWindow) BOOL inWindow; -// Private API for helper funcitons / unit tests. Use ASDisplayNodeDisableHierarchyNotifications() to control this. +// Private API for helper functions / unit tests. Use ASDisplayNodeDisableHierarchyNotifications() to control this. - (BOOL)__visibilityNotificationsDisabled; - (void)__incrementVisibilityNotificationsDisabled; - (void)__decrementVisibilityNotificationsDisabled; From 51f3073c33ddd2e129c9581174744c9a7c2ceea8 Mon Sep 17 00:00:00 2001 From: Nadine Salter Date: Tue, 2 Dec 2014 17:56:40 -0800 Subject: [PATCH 2/3] ASDisplayNode.inWindow -> .inHierarchy. This is a remnant from before `willAppear` and `didDisappear` were renamed to better reflect their hierarchy-change status (being added to the hierarchy != being visible). May be useful for turians. --- AsyncDisplayKit/ASDisplayNode+Subclasses.h | 2 +- AsyncDisplayKit/ASDisplayNode.mm | 20 ++--- AsyncDisplayKit/Details/_ASDisplayView.mm | 4 +- .../Private/ASDisplayNodeInternal.h | 10 +-- .../ASDisplayNodeAppearanceTests.m | 88 +++++++++---------- 5 files changed, 62 insertions(+), 62 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode+Subclasses.h b/AsyncDisplayKit/ASDisplayNode+Subclasses.h index f8602a39bd..16a1ea7b32 100644 --- a/AsyncDisplayKit/ASDisplayNode+Subclasses.h +++ b/AsyncDisplayKit/ASDisplayNode+Subclasses.h @@ -63,7 +63,7 @@ /** * @abstract Whether the view or layer of this display node is currently in a window */ -@property (nonatomic, readonly, assign, getter=isInWindow) BOOL inWindow; +@property (nonatomic, readonly, assign, getter=isInHierarchy) BOOL inHierarchy; /** @name View Lifecycle */ diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 8e056e7168..5ec6221d7a 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -109,7 +109,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) _displaySentinel = [[ASSentinel alloc] init]; - _flags.isInWindow = NO; + _flags.isInHierarchy = NO; _flags.displaysAsynchronously = YES; // As an optimization, it may be worth a caching system that performs these checks once per class in +initialize (see above). @@ -660,7 +660,7 @@ static bool disableNotificationsForMovingBetweenParents(ASDisplayNode *from, ASD if (!from || !to) return NO; if (from->_flags.synchronous) return NO; if (to->_flags.synchronous) return NO; - if (from->_flags.isInWindow != to->_flags.isInWindow) return NO; + if (from->_flags.isInHierarchy != to->_flags.isInHierarchy) return NO; return YES; } @@ -1021,8 +1021,8 @@ static NSInteger incrementIfFound(NSInteger i) { { ASDisplayNodeAssertMainThread(); ASDisplayNodeAssert(!_flags.isEnteringHierarchy, @"Should not cause recursive __enterHierarchy"); - if (!self.inWindow && !_flags.visibilityNotificationsDisabled && ![self __hasParentWithVisibilityNotificationsDisabled]) { - self.inWindow = YES; + if (!self.inHierarchy && !_flags.visibilityNotificationsDisabled && ![self __hasParentWithVisibilityNotificationsDisabled]) { + self.inHierarchy = YES; _flags.isEnteringHierarchy = YES; if (self.shouldRasterizeDescendants) { // Nodes that are descendants of a rasterized container do not have views or layers, and so cannot receive visibility notifications directly via orderIn/orderOut CALayer actions. Manually send visibility notifications to rasterized descendants. @@ -1043,8 +1043,8 @@ static NSInteger incrementIfFound(NSInteger i) { { ASDisplayNodeAssertMainThread(); ASDisplayNodeAssert(!_flags.isExitingHierarchy, @"Should not cause recursive __exitHierarchy"); - if (self.inWindow && !_flags.visibilityNotificationsDisabled && ![self __hasParentWithVisibilityNotificationsDisabled]) { - self.inWindow = NO; + if (self.inHierarchy && !_flags.visibilityNotificationsDisabled && ![self __hasParentWithVisibilityNotificationsDisabled]) { + self.inHierarchy = NO; [self.asyncLayer cancelAsyncDisplay]; @@ -1417,20 +1417,20 @@ static void _recursiveSetPreventOrCancelDisplay(ASDisplayNode *node, CALayer *la self.asyncLayer.displaySuspended = flag; } -- (BOOL)isInWindow +- (BOOL)isInHierarchy { ASDisplayNodeAssertThreadAffinity(self); ASDN::MutexLocker l(_propertyLock); - return _flags.isInWindow; + return _flags.isInHierarchy; } -- (void)setInWindow:(BOOL)inWindow +- (void)setInHierarchy:(BOOL)inHierarchy { ASDisplayNodeAssertThreadAffinity(self); ASDN::MutexLocker l(_propertyLock); - _flags.isInWindow = inWindow; + _flags.isInHierarchy = inHierarchy; } + (dispatch_queue_t)asyncSizingQueue diff --git a/AsyncDisplayKit/Details/_ASDisplayView.mm b/AsyncDisplayKit/Details/_ASDisplayView.mm index 86f1f8e8fa..a2470d2353 100644 --- a/AsyncDisplayKit/Details/_ASDisplayView.mm +++ b/AsyncDisplayKit/Details/_ASDisplayView.mm @@ -80,9 +80,9 @@ - (void)willMoveToWindow:(UIWindow *)newWindow { BOOL visible = newWindow != nil; - if (visible && !_node.inWindow) { + if (visible && !_node.inHierarchy) { [_node __enterHierarchy]; - } else if (!visible && _node.inWindow) { + } else if (!visible && _node.inHierarchy) { [_node __exitHierarchy]; } } diff --git a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h index 657361b926..821fb2f175 100644 --- a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h +++ b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h @@ -72,7 +72,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()); unsigned isMeasured:1; unsigned isEnteringHierarchy:1; unsigned isExitingHierarchy:1; - unsigned isInWindow:1; + unsigned isInHierarchy:1; unsigned visibilityNotificationsDisabled:VISIBILITY_NOTIFICATIONS_DISABLED_BITS; } _flags; @@ -102,17 +102,17 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()); - (void)__layout; - (void)__setSupernode:(ASDisplayNode *)supernode; -// The visibility state of the node. Changed before calling willAppear, willDisappear, and didDisappear. -@property (nonatomic, readwrite, assign, getter = isInWindow) BOOL inWindow; +// Changed before calling willEnterHierarchy / didExitHierarchy. +@property (nonatomic, readwrite, assign, getter = isInHierarchy) BOOL inHierarchy; // Private API for helper functions / unit tests. Use ASDisplayNodeDisableHierarchyNotifications() to control this. - (BOOL)__visibilityNotificationsDisabled; - (void)__incrementVisibilityNotificationsDisabled; - (void)__decrementVisibilityNotificationsDisabled; -// Call willEnterHierarchy if necessary and set inWindow = YES if visibility notifications are enabled on all of its parents +// Call willEnterHierarchy if necessary and set inHierarchy = YES if visibility notifications are enabled on all of its parents - (void)__enterHierarchy; -// Call didExitHierarchy if necessary and set inWindow = NO if visibility notifications are enabled on all of its parents +// Call didExitHierarchy if necessary and set inHierarchy = NO if visibility notifications are enabled on all of its parents - (void)__exitHierarchy; // Returns the ancestor node that rasterizes descendants, or nil if none. diff --git a/AsyncDisplayKitTests/ASDisplayNodeAppearanceTests.m b/AsyncDisplayKitTests/ASDisplayNodeAppearanceTests.m index 118b274088..78e2fdb978 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeAppearanceTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeAppearanceTests.m @@ -139,7 +139,7 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C XCTAssertEqual([_willEnterHierarchyCounts countForObject:n], 1u, @"willEnterHierarchy not called when node's view added to hierarchy"); XCTAssertEqual([_didExitHierarchyCounts countForObject:n], 0u, @"didExitHierarchy erroneously called"); - XCTAssertTrue(n.inWindow, @"Node should be visible"); + XCTAssertTrue(n.inHierarchy, @"Node should be visible"); if (isLayerBacked) { [n.layer removeFromSuperlayer]; @@ -147,7 +147,7 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C [n.view removeFromSuperview]; } - XCTAssertFalse(n.inWindow, @"Node should be not visible"); + XCTAssertFalse(n.inHierarchy, @"Node should be not visible"); XCTAssertEqual([_willEnterHierarchyCounts countForObject:n], 1u, @"willEnterHierarchy not called when node's view added to hierarchy"); XCTAssertEqual([_didExitHierarchyCounts countForObject:n], 1u, @"didExitHierarchy erroneously called"); @@ -175,11 +175,11 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C [parent addSubnode:a]; - XCTAssertFalse(parent.inWindow, @"Nothing should be visible"); - XCTAssertFalse(a.inWindow, @"Nothing should be visible"); - XCTAssertFalse(b.inWindow, @"Nothing should be visible"); - XCTAssertFalse(aa.inWindow, @"Nothing should be visible"); - XCTAssertFalse(ab.inWindow, @"Nothing should be visible"); + XCTAssertFalse(parent.inHierarchy, @"Nothing should be visible"); + XCTAssertFalse(a.inHierarchy, @"Nothing should be visible"); + XCTAssertFalse(b.inHierarchy, @"Nothing should be visible"); + XCTAssertFalse(aa.inHierarchy, @"Nothing should be visible"); + XCTAssertFalse(ab.inHierarchy, @"Nothing should be visible"); if (isLayerBacked) { [window.layer addSublayer:parent.layer]; @@ -193,22 +193,22 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C XCTAssertEqual([_willEnterHierarchyCounts countForObject:aa], 0u, @"Should not have appeared yet"); XCTAssertEqual([_willEnterHierarchyCounts countForObject:ab], 0u, @"Should not have appeared yet"); - XCTAssertTrue(parent.inWindow, @"Should be visible"); - XCTAssertTrue(a.inWindow, @"Should be visible"); - XCTAssertFalse(b.inWindow, @"Nothing should be visible"); - XCTAssertFalse(aa.inWindow, @"Nothing should be visible"); - XCTAssertFalse(ab.inWindow, @"Nothing should be visible"); + XCTAssertTrue(parent.inHierarchy, @"Should be visible"); + XCTAssertTrue(a.inHierarchy, @"Should be visible"); + XCTAssertFalse(b.inHierarchy, @"Nothing should be visible"); + XCTAssertFalse(aa.inHierarchy, @"Nothing should be visible"); + XCTAssertFalse(ab.inHierarchy, @"Nothing should be visible"); // Add to an already-visible node should make the node visible [parent addSubnode:b]; [a insertSubnode:aa atIndex:0]; [a insertSubnode:ab aboveSubnode:aa]; - XCTAssertTrue(parent.inWindow, @"Should be visible"); - XCTAssertTrue(a.inWindow, @"Should be visible"); - XCTAssertTrue(b.inWindow, @"Should be visible after adding to visible parent"); - XCTAssertTrue(aa.inWindow, @"Nothing should be visible"); - XCTAssertTrue(ab.inWindow, @"Nothing should be visible"); + XCTAssertTrue(parent.inHierarchy, @"Should be visible"); + XCTAssertTrue(a.inHierarchy, @"Should be visible"); + XCTAssertTrue(b.inHierarchy, @"Should be visible after adding to visible parent"); + XCTAssertTrue(aa.inHierarchy, @"Nothing should be visible"); + XCTAssertTrue(ab.inHierarchy, @"Nothing should be visible"); XCTAssertEqual([_willEnterHierarchyCounts countForObject:parent], 1u, @"Should have -willEnterHierarchy called once"); XCTAssertEqual([_willEnterHierarchyCounts countForObject:a], 1u, @"Should have -willEnterHierarchy called once"); @@ -222,11 +222,11 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C [parent.view removeFromSuperview]; } - XCTAssertFalse(parent.inWindow, @"Nothing should be visible"); - XCTAssertFalse(a.inWindow, @"Nothing should be visible"); - XCTAssertFalse(b.inWindow, @"Nothing should be visible"); - XCTAssertFalse(aa.inWindow, @"Nothing should be visible"); - XCTAssertFalse(ab.inWindow, @"Nothing should be visible"); + XCTAssertFalse(parent.inHierarchy, @"Nothing should be visible"); + XCTAssertFalse(a.inHierarchy, @"Nothing should be visible"); + XCTAssertFalse(b.inHierarchy, @"Nothing should be visible"); + XCTAssertFalse(aa.inHierarchy, @"Nothing should be visible"); + XCTAssertFalse(ab.inHierarchy, @"Nothing should be visible"); } - (void)testAppearanceMethodsNoLayer @@ -262,36 +262,36 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C [parentSynchronousNode addSubnode:layerBackedNode]; [parentSynchronousNode addSubnode:viewBackedNode]; - XCTAssertFalse(parentSynchronousNode.inWindow, @"Should not yet be visible"); - XCTAssertFalse(layerBackedNode.inWindow, @"Should not yet be visible"); - XCTAssertFalse(viewBackedNode.inWindow, @"Should not yet be visible"); + XCTAssertFalse(parentSynchronousNode.inHierarchy, @"Should not yet be visible"); + XCTAssertFalse(layerBackedNode.inHierarchy, @"Should not yet be visible"); + XCTAssertFalse(viewBackedNode.inHierarchy, @"Should not yet be visible"); [window addSubview:parentSynchronousNode.view]; // This is a known case that isn't supported - XCTAssertFalse(parentSynchronousNode.inWindow, @"Synchronous views are not currently marked visible"); + XCTAssertFalse(parentSynchronousNode.inHierarchy, @"Synchronous views are not currently marked visible"); - XCTAssertTrue(layerBackedNode.inWindow, @"Synchronous views' subviews should get marked visible"); - XCTAssertTrue(viewBackedNode.inWindow, @"Synchronous views' subviews should get marked visible"); + XCTAssertTrue(layerBackedNode.inHierarchy, @"Synchronous views' subviews should get marked visible"); + XCTAssertTrue(viewBackedNode.inHierarchy, @"Synchronous views' subviews should get marked visible"); // Try moving a node to/from a synchronous node in the window with the node API // Setup [layerBackedNode removeFromSupernode]; [viewBackedNode removeFromSupernode]; - XCTAssertFalse(layerBackedNode.inWindow, @"aoeu"); - XCTAssertFalse(viewBackedNode.inWindow, @"aoeu"); + XCTAssertFalse(layerBackedNode.inHierarchy, @"aoeu"); + XCTAssertFalse(viewBackedNode.inHierarchy, @"aoeu"); // now move to synchronous node [parentSynchronousNode addSubnode:layerBackedNode]; [parentSynchronousNode insertSubnode:viewBackedNode aboveSubnode:layerBackedNode]; - XCTAssertTrue(layerBackedNode.inWindow, @"Synchronous views' subviews should get marked visible"); - XCTAssertTrue(viewBackedNode.inWindow, @"Synchronous views' subviews should get marked visible"); + XCTAssertTrue(layerBackedNode.inHierarchy, @"Synchronous views' subviews should get marked visible"); + XCTAssertTrue(viewBackedNode.inHierarchy, @"Synchronous views' subviews should get marked visible"); [parentSynchronousNode.view removeFromSuperview]; - XCTAssertFalse(parentSynchronousNode.inWindow, @"Should not have changed"); - XCTAssertFalse(layerBackedNode.inWindow, @"Should have been marked invisible when synchronous superview was removed from the window"); - XCTAssertFalse(viewBackedNode.inWindow, @"Should have been marked invisible when synchronous superview was removed from the window"); + XCTAssertFalse(parentSynchronousNode.inHierarchy, @"Should not have changed"); + XCTAssertFalse(layerBackedNode.inHierarchy, @"Should have been marked invisible when synchronous superview was removed from the window"); + XCTAssertFalse(viewBackedNode.inHierarchy, @"Should have been marked invisible when synchronous superview was removed from the window"); [window release]; [parentSynchronousNode release]; @@ -315,11 +315,11 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C [parentA addSubnode:child]; [child addSubnode:childSubnode]; - XCTAssertFalse(parentA.inWindow, @"Should not yet be visible"); - XCTAssertFalse(parentB.inWindow, @"Should not yet be visible"); - XCTAssertFalse(child.inWindow, @"Should not yet be visible"); - XCTAssertFalse(childSubnode.inWindow, @"Should not yet be visible"); - XCTAssertFalse(childSubnode.inWindow, @"Should not yet be visible"); + XCTAssertFalse(parentA.inHierarchy, @"Should not yet be visible"); + XCTAssertFalse(parentB.inHierarchy, @"Should not yet be visible"); + XCTAssertFalse(child.inHierarchy, @"Should not yet be visible"); + XCTAssertFalse(childSubnode.inHierarchy, @"Should not yet be visible"); + XCTAssertFalse(childSubnode.inHierarchy, @"Should not yet be visible"); XCTAssertEqual([_willEnterHierarchyCounts countForObject:child], 0u, @"Should not have -willEnterHierarchy called"); XCTAssertEqual([_willEnterHierarchyCounts countForObject:childSubnode], 0u, @"Should not have -willEnterHierarchy called"); @@ -332,10 +332,10 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C [window addSubview:parentB.view]; } - XCTAssertTrue(parentA.inWindow, @"Should be visible after added to window"); - XCTAssertTrue(parentB.inWindow, @"Should be visible after added to window"); - XCTAssertTrue(child.inWindow, @"Should be visible after parent added to window"); - XCTAssertTrue(childSubnode.inWindow, @"Should be visible after parent added to window"); + XCTAssertTrue(parentA.inHierarchy, @"Should be visible after added to window"); + XCTAssertTrue(parentB.inHierarchy, @"Should be visible after added to window"); + XCTAssertTrue(child.inHierarchy, @"Should be visible after parent added to window"); + XCTAssertTrue(childSubnode.inHierarchy, @"Should be visible after parent added to window"); XCTAssertEqual([_willEnterHierarchyCounts countForObject:child], 1u, @"Should have -willEnterHierarchy called once"); XCTAssertEqual([_willEnterHierarchyCounts countForObject:childSubnode], 1u, @"Should have -willEnterHierarchy called once"); From 1103f82a5cfdad72149c8e9f70e6281a5138a07f Mon Sep 17 00:00:00 2001 From: Nadine Salter Date: Tue, 2 Dec 2014 18:03:30 -0800 Subject: [PATCH 3/3] .preventOrCancelDisplay -> .displaySuspended. Rename the ASDisplayNode property to match its _ASDisplayLayer counterpart -- `displaySuspended` is more succinct and is a more plausible name for a Cocoa BOOL property. --- AsyncDisplayKit/ASDisplayNode.h | 14 +++++------ AsyncDisplayKit/ASDisplayNode.mm | 24 +++++++++---------- AsyncDisplayKit/ASImageNode.h | 4 ++-- AsyncDisplayKit/ASImageNode.mm | 2 +- AsyncDisplayKit/Details/ASRangeController.mm | 4 ++-- .../Private/ASDisplayNodeInternal.h | 2 +- AsyncDisplayKitTests/ASDisplayNodeTests.m | 8 +++---- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index c8b20a0e07..8af6efba80 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -319,31 +319,31 @@ * progress. * * Defaults to NO. Does not control display for any child or descendant nodes; for that, use - * -recursiveSetPreventOrCancelDisplay:. + * -recursivelySetDisplaySuspended:. * - * If a setNeedsDisplay occurs while preventOrCancelDisplay is YES, and preventOrCancelDisplay is set to NO, then the + * If a setNeedsDisplay occurs while displaySuspended is YES, and displaySuspended is set to NO, then the * layer will be automatically displayed. */ -@property (nonatomic, assign) BOOL preventOrCancelDisplay; +@property (nonatomic, assign) BOOL displaySuspended; /** * @abstract Prevent the node and its descendants' layer from displaying. * * @param flag YES if display should be prevented or cancelled; NO otherwise. * - * @see preventOrCancelDisplay + * @see displaySuspended */ -- (void)recursiveSetPreventOrCancelDisplay:(BOOL)flag; +- (void)recursivelySetDisplaySuspended:(BOOL)flag; /** * @abstract Calls -reclaimMemory on the receiver and its subnode hierarchy. * * @discussion Clears backing stores and other memory-intensive intermediates. * If the node is removed from a visible hierarchy and then re-added, it will automatically trigger a new asynchronous display, - * as long as preventOrCancelDisplay is not set. + * as long as displaySuspended is not set. * If the node remains in the hierarchy throughout, -setNeedsDisplay is required to trigger a new asynchronous display. * - * @see preventOrCancelDisplay and setNeedsDisplay + * @see displaySuspended and setNeedsDisplay */ - (void)recursivelyReclaimMemory; diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 5ec6221d7a..d9a8305394 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1326,7 +1326,7 @@ static NSInteger incrementIfFound(NSInteger i) { _pendingViewState = nil; // TODO: move this into real pending state - if (_flags.preventOrCancelDisplay) { + if (_flags.displaySuspended) { self.asyncLayer.displaySuspended = YES; } if (!_flags.displaysAsynchronously) { @@ -1359,12 +1359,12 @@ static NSInteger incrementIfFound(NSInteger i) { return nil; } -- (void)recursiveSetPreventOrCancelDisplay:(BOOL)flag +- (void)recursivelySetDisplaySuspended:(BOOL)flag { - _recursiveSetPreventOrCancelDisplay(self, nil, flag); + _recursivelySetDisplaySuspended(self, nil, flag); } -static void _recursiveSetPreventOrCancelDisplay(ASDisplayNode *node, CALayer *layer, BOOL flag) +static void _recursivelySetDisplaySuspended(ASDisplayNode *node, CALayer *layer, BOOL flag) { // If there is no layer, but node whose its view is loaded, then we can traverse down its layer hierarchy. Otherwise we must stick to the node hierarchy to avoid loading views prematurely. Note that for nodes that haven't loaded their views, they can't possibly have subviews/sublayers, so we don't need to traverse the layer hierarchy for them. if (!layer && node && node.nodeLoaded) { @@ -1377,29 +1377,29 @@ static void _recursiveSetPreventOrCancelDisplay(ASDisplayNode *node, CALayer *la } // Set the flag on the node. If this is a pure layer (no node) then this has no effect (plain layers don't support preventing/cancelling display). - node.preventOrCancelDisplay = flag; + node.displaySuspended = flag; if (layer && !node.shouldRasterizeDescendants) { // If there is a layer, recurse down the layer hierarchy to set the flag on descendants. This will cover both layer-based and node-based children. for (CALayer *sublayer in layer.sublayers) { - _recursiveSetPreventOrCancelDisplay(nil, sublayer, flag); + _recursivelySetDisplaySuspended(nil, sublayer, flag); } } else { // If there is no layer (view not loaded yet) or this node rasterizes descendants (there won't be a layer tree to traverse), recurse down the subnode hierarchy to set the flag on descendants. This covers only node-based children, but for a node whose view is not loaded it can't possibly have nodeless children. for (ASDisplayNode *subnode in node.subnodes) { - _recursiveSetPreventOrCancelDisplay(subnode, nil, flag); + _recursivelySetDisplaySuspended(subnode, nil, flag); } } } -- (BOOL)preventOrCancelDisplay +- (BOOL)displaySuspended { ASDisplayNodeAssertThreadAffinity(self); ASDN::MutexLocker l(_propertyLock); - return _flags.preventOrCancelDisplay; + return _flags.displaySuspended; } -- (void)setPreventOrCancelDisplay:(BOOL)flag +- (void)setDisplaySuspended:(BOOL)flag { ASDisplayNodeAssertThreadAffinity(self); @@ -1409,10 +1409,10 @@ static void _recursiveSetPreventOrCancelDisplay(ASDisplayNode *node, CALayer *la ASDN::MutexLocker l(_propertyLock); - if (_flags.preventOrCancelDisplay == flag) + if (_flags.displaySuspended == flag) return; - _flags.preventOrCancelDisplay = flag; + _flags.displaySuspended = flag; self.asyncLayer.displaySuspended = flag; } diff --git a/AsyncDisplayKit/ASImageNode.h b/AsyncDisplayKit/ASImageNode.h index d1c4aa840b..d4c0ae102c 100644 --- a/AsyncDisplayKit/ASImageNode.h +++ b/AsyncDisplayKit/ASImageNode.h @@ -107,10 +107,10 @@ typedef UIImage *(^asimagenode_modification_block_t)(UIImage *image); * * @param displayCompletionBlock The block to be performed after display has * finished. Its `canceled` property will be YES if display was prevented or - * canceled (via preventOrCancelDisplay); NO otherwise. + * canceled (via displaySuspended); NO otherwise. * * @discussion displayCompletionBlock will be performed on the main-thread. If - * `preventOrCancelDisplay` is YES, `displayCompletionBlock` is will be + * `displaySuspended` is YES, `displayCompletionBlock` is will be * performed immediately and `YES` will be passed for `canceled`. */ - (void)setNeedsDisplayWithCompletion:(void (^)(BOOL canceled))displayCompletionBlock; diff --git a/AsyncDisplayKit/ASImageNode.mm b/AsyncDisplayKit/ASImageNode.mm index 41b8c6b6e9..5f532aadea 100644 --- a/AsyncDisplayKit/ASImageNode.mm +++ b/AsyncDisplayKit/ASImageNode.mm @@ -263,7 +263,7 @@ #pragma mark - - (void)setNeedsDisplayWithCompletion:(void (^)(BOOL canceled))displayCompletionBlock { - if (self.preventOrCancelDisplay) { + if (self.displaySuspended) { if (displayCompletionBlock) displayCompletionBlock(YES); return; diff --git a/AsyncDisplayKit/Details/ASRangeController.mm b/AsyncDisplayKit/Details/ASRangeController.mm index 4bfbad5f83..64bc6ccd5c 100644 --- a/AsyncDisplayKit/Details/ASRangeController.mm +++ b/AsyncDisplayKit/Details/ASRangeController.mm @@ -187,7 +187,7 @@ static BOOL ASRangeIsValid(NSRange range) ASDisplayNodeAssertMainThread(); ASDisplayNodeAssert(node, @"invalid argument"); - [node recursiveSetPreventOrCancelDisplay:YES]; + [node recursivelySetDisplaySuspended:YES]; [node.view removeFromSuperview]; // since this class usually manages large or infinite data sets, the working range @@ -526,7 +526,7 @@ static NSRange ASCalculateWorkingRange(ASRangeTuningParameters params, ASScrollD ASCellNode *sizedNode = _nodes[[NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section]]; ASDisplayNodeAssert(sizedNode, @"this node should be sized but doesn't even exist"); ASDisplayNodeAssert([sizedNode.asyncdisplaykit_indexPath isEqual:indexPath], @"this node has the wrong index path"); - [sizedNode recursiveSetPreventOrCancelDisplay:NO]; + [sizedNode recursivelySetDisplaySuspended:NO]; return sizedNode; } diff --git a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h index 821fb2f175..15d4258ea8 100644 --- a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h +++ b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h @@ -61,7 +61,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()); unsigned layerBacked:1; unsigned displaysAsynchronously:1; unsigned shouldRasterizeDescendants:1; - unsigned preventOrCancelDisplay:1; + unsigned displaySuspended:1; // whether custom drawing is enabled unsigned implementsDrawRect:1; diff --git a/AsyncDisplayKitTests/ASDisplayNodeTests.m b/AsyncDisplayKitTests/ASDisplayNodeTests.m index 10d805a747..fbb652ec98 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeTests.m @@ -149,7 +149,7 @@ for (ASDisplayNode *n in @[ nodes ]) {\ XCTAssertEqual(3.f, node.shadowRadius, @"default shadowRadius broken %@", hasLoadedView); XCTAssertEqual(0.0f, node.borderWidth, @"default borderWidth broken %@", hasLoadedView); XCTAssertEqualObjects(rgbBlackCGColorIdPtr, (id)node.borderColor, @"default borderColor broken %@", hasLoadedView); - XCTAssertEqual(NO, node.preventOrCancelDisplay, @"default preventOrCancelDisplay broken %@", hasLoadedView); + XCTAssertEqual(NO, node.displaySuspended, @"default displaySuspended broken %@", hasLoadedView); XCTAssertEqual(YES, node.displaysAsynchronously, @"default displaysAsynchronously broken %@", hasLoadedView); XCTAssertEqual(NO, node.asyncdisplaykit_asyncTransactionContainer, @"default asyncdisplaykit_asyncTransactionContainer broken %@", hasLoadedView); XCTAssertEqualObjects(nil, node.name, @"default name broken %@", hasLoadedView); @@ -245,8 +245,8 @@ for (ASDisplayNode *n in @[ nodes ]) {\ XCTAssertEqual(.5f, node.shadowRadius, @"shadowRadius broken %@", hasLoadedView); XCTAssertEqual(.5f, node.borderWidth, @"borderWidth broken %@", hasLoadedView); XCTAssertEqual([[UIColor orangeColor] CGColor], node.borderColor, @"borderColor broken %@", hasLoadedView); - XCTAssertEqual(YES, node.preventOrCancelDisplay, @"preventOrCancelDisplay broken %@", hasLoadedView); - XCTAssertEqual(NO, node.displaysAsynchronously, @"preventOrCancelDisplay broken %@", hasLoadedView); + XCTAssertEqual(YES, node.displaySuspended, @"displaySuspended broken %@", hasLoadedView); + XCTAssertEqual(NO, node.displaysAsynchronously, @"displaySuspended broken %@", hasLoadedView); XCTAssertEqual(YES, node.asyncdisplaykit_asyncTransactionContainer, @"asyncTransactionContainer broken %@", hasLoadedView); XCTAssertEqual(NO, node.userInteractionEnabled, @"userInteractionEnabled broken %@", hasLoadedView); XCTAssertEqual((BOOL)!isLayerBacked, node.exclusiveTouch, @"exclusiveTouch broken %@", hasLoadedView); @@ -298,7 +298,7 @@ for (ASDisplayNode *n in @[ nodes ]) {\ node.shadowRadius = .5f; node.borderWidth = .5f; node.borderColor = [[UIColor orangeColor] CGColor]; - node.preventOrCancelDisplay = YES; + node.displaySuspended = YES; node.displaysAsynchronously = NO; node.asyncdisplaykit_asyncTransactionContainer = YES; node.userInteractionEnabled = NO;