diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 56f7f85458..7ad4ee3b6c 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -83,6 +83,13 @@ BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector) return ASSubclassOverridesSelector([ASDisplayNode class], subclass, selector); } +// For classes like ASTableNode, ASCollectionNode, ASScrollNode and similar - we have to be sure to set certain properties +// like setFrame: and setBackgroundColor: directly to the UIView and not apply it to the layer only. +BOOL ASDisplayNodeNeedsSpecialPropertiesSettingHandlingForFlags(ASDisplayNodeFlags flags) +{ + return flags.synchronous && !flags.layerBacked; +} + _ASPendingState *ASDisplayNodeGetPendingState(ASDisplayNode *node) { ASDN::MutexLocker l(node->_propertyLock); @@ -954,8 +961,8 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) if (self.layerBacked) { [_pendingViewState applyToLayer:self.layer]; } else { - BOOL setFrameDirectly = (_flags.synchronous && !_flags.layerBacked); - [_pendingViewState applyToView:self.view setFrameDirectly:setFrameDirectly]; + BOOL specialPropertiesHandling = ASDisplayNodeNeedsSpecialPropertiesSettingHandlingForFlags(_flags); + [_pendingViewState applyToView:self.view withSpecialPropertiesHandling:specialPropertiesHandling]; } [_pendingViewState clearChanges]; diff --git a/AsyncDisplayKit/ASTableNode.m b/AsyncDisplayKit/ASTableNode.m index 366209bf15..22b6c3926f 100644 --- a/AsyncDisplayKit/ASTableNode.m +++ b/AsyncDisplayKit/ASTableNode.m @@ -20,7 +20,7 @@ @end @interface ASTableNode () -@property (nonatomic) _ASTablePendingState *pendingState; +@property (nonatomic, strong) _ASTablePendingState *pendingState; @end @interface ASTableView () @@ -68,7 +68,7 @@ ASTableView *view = self.view; view.tableNode = self; - + if (_pendingState) { _ASTablePendingState *pendingState = _pendingState; self.pendingState = nil; diff --git a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm index eaf0cc9f59..c777857485 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm +++ b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm @@ -19,6 +19,7 @@ #import "ASPendingStateController.h" #import "ASThread.h" #import "ASTextNode.h" +#import "ASTableNode.h" /** * The following macros are conveniences to help in the common tasks related to the bridging that ASDisplayNode does to UIView and CALayer. @@ -239,11 +240,11 @@ if (shouldApply) { _layer.layerProperty = (layerValueExpr); } else { ASDisplayNo // For classes like ASTableNode, ASCollectionNode, ASScrollNode and similar - make sure UIView gets setFrame: struct ASDisplayNodeFlags flags = _flags; - BOOL setFrameDirectly = flags.synchronous && !flags.layerBacked; + BOOL specialPropertiesHandling = ASDisplayNodeNeedsSpecialPropertiesSettingHandlingForFlags(flags); BOOL nodeLoaded = __loaded(self); BOOL isMainThread = ASDisplayNodeThreadIsMain(); - if (!setFrameDirectly) { + if (!specialPropertiesHandling) { BOOL canReadProperties = isMainThread || !nodeLoaded; if (canReadProperties) { // We don't have to set frame directly, and we can read current properties. @@ -583,6 +584,12 @@ if (shouldApply) { _layer.layerProperty = (layerValueExpr); } else { ASDisplayNo if (shouldApply) { CGColorRef oldBackgroundCGColor = _layer.backgroundColor; _layer.backgroundColor = newBackgroundCGColor; + + BOOL specialPropertiesHandling = ASDisplayNodeNeedsSpecialPropertiesSettingHandlingForFlags(_flags); + if (specialPropertiesHandling) { + _view.backgroundColor = newBackgroundColor; + } + if (!CGColorEqualToColor(oldBackgroundCGColor, newBackgroundCGColor)) { [self setNeedsDisplay]; } diff --git a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h index ae3f3c477a..ae7616add2 100644 --- a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h +++ b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h @@ -25,8 +25,10 @@ @class _ASDisplayLayer; @class _ASPendingState; @class ASSentinel; +struct ASDisplayNodeFlags; BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector); +BOOL ASDisplayNodeNeedsSpecialPropertiesSettingHandlingForFlags(ASDisplayNodeFlags flags); /// Get the pending view state for the node, creating one if needed. _ASPendingState *ASDisplayNodeGetPendingState(ASDisplayNode *node); diff --git a/AsyncDisplayKit/Private/_ASPendingState.h b/AsyncDisplayKit/Private/_ASPendingState.h index 8f6702465f..40986b18af 100644 --- a/AsyncDisplayKit/Private/_ASPendingState.h +++ b/AsyncDisplayKit/Private/_ASPendingState.h @@ -24,7 +24,7 @@ // Supports all of the properties included in the ASDisplayNodeViewProperties protocol -- (void)applyToView:(UIView *)view setFrameDirectly:(BOOL)setFrameDirectly; +- (void)applyToView:(UIView *)view withSpecialPropertiesHandling:(BOOL)setFrameDirectly; - (void)applyToLayer:(CALayer *)layer; + (_ASPendingState *)pendingViewStateFromLayer:(CALayer *)layer; diff --git a/AsyncDisplayKit/Private/_ASPendingState.mm b/AsyncDisplayKit/Private/_ASPendingState.mm index b85cbb57c3..303bf2a58c 100644 --- a/AsyncDisplayKit/Private/_ASPendingState.mm +++ b/AsyncDisplayKit/Private/_ASPendingState.mm @@ -745,7 +745,7 @@ static UIColor *defaultTintColor = nil; ASPendingStateApplyMetricsToLayer(self, layer); } -- (void)applyToView:(UIView *)view setFrameDirectly:(BOOL)setFrameDirectly +- (void)applyToView:(UIView *)view withSpecialPropertiesHandling:(BOOL)specialPropertiesHandling { /* Use our convenience setters blah here instead of layer.blah @@ -789,9 +789,16 @@ static UIColor *defaultTintColor = nil; if (flags.setClipsToBounds) view.clipsToBounds = clipsToBounds; - if (flags.setBackgroundColor) + if (flags.setBackgroundColor) { + // Set the background color to the layer as in the UIView bridge we use this value as background color layer.backgroundColor = backgroundColor; + // We have to make sure certain nodes get the background color call directly + if (specialPropertiesHandling) { + view.backgroundColor = [UIColor colorWithCGColor:backgroundColor]; + } + } + if (flags.setTintColor) view.tintColor = self.tintColor; @@ -907,8 +914,7 @@ static UIColor *defaultTintColor = nil; if (flags.setAccessibilityPath) view.accessibilityPath = accessibilityPath; - // For classes like ASTableNode, ASCollectionNode, ASScrollNode and similar - make sure UIView gets setFrame: - if (flags.setFrame && setFrameDirectly) { + if (flags.setFrame && specialPropertiesHandling) { // Frame is only defined when transform is identity because we explicitly diverge from CALayer behavior and define frame without transform #if DEBUG // Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of.