From a30c087616b8a57a802bc63b01368654656a53e5 Mon Sep 17 00:00:00 2001 From: Nadine Salter Date: Tue, 2 Dec 2014 16:53:02 -0800 Subject: [PATCH] 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;