diff --git a/Source/ASDisplayNode.h b/Source/ASDisplayNode.h index 57d9cf7fc..35dfe3c3a 100644 --- a/Source/ASDisplayNode.h +++ b/Source/ASDisplayNode.h @@ -705,7 +705,13 @@ AS_EXTERN NSInteger const ASDefaultDrawingPriority; @property (nullable, copy) UIColor *backgroundColor; // default=nil @property (null_resettable, copy) UIColor *tintColor; // default=Blue -- (void)tintColorDidChange; // Notifies the node when the tintColor has changed. + +/** + * Notifies the node when the tintColor has changed. + * + * @note This method is guaranteed to be called if the tintColor is changed after the node loaded. + */ +- (void)tintColorDidChange; /** * @abstract A flag used to determine how a node lays out its content when its bounds change. diff --git a/Source/Private/ASDisplayNode+UIViewBridge.mm b/Source/Private/ASDisplayNode+UIViewBridge.mm index 77042d528..258aa4c09 100644 --- a/Source/Private/ASDisplayNode+UIViewBridge.mm +++ b/Source/Private/ASDisplayNode+UIViewBridge.mm @@ -795,47 +795,37 @@ - (void)setBackgroundColor:(UIColor *)newBackgroundColor - (UIColor *)tintColor { __instanceLock__.lock(); - UIColor *retVal; - if (_loaded(self)) { - if (_flags.layerBacked) { - // The first nondefault tint color value in the view’s hierarchy, ascending from and starting with the view itself. - retVal = _tintColor; - } else { - retVal = _getFromViewOnly(tintColor); - } + UIColor *retVal = nil; + BOOL shouldAscend = NO; + if (_flags.layerBacked) { + retVal = _tintColor; + // The first nondefault tint color value in the node’s hierarchy, ascending from and starting with the node itself. + shouldAscend = (retVal == nil); } else { - if (_flags.layerBacked) { - retVal = _tintColor; - } else { - retVal = ASDisplayNodeGetPendingState(self).tintColor; - } + ASDisplayNodeAssertThreadAffinity(self); + retVal = _getFromViewOnly(tintColor); } __instanceLock__.unlock(); - return retVal ?: self.supernode.tintColor; + return shouldAscend ? self.supernode.tintColor : retVal; } - (void)setTintColor:(UIColor *)color { // Handle locking manually since we unlock to notify subclasses when tint color changes __instanceLock__.lock(); - if (_loaded(self)) { - if (_flags.layerBacked) { - if (![_tintColor isEqual:color]) { - _tintColor = color; + if (_flags.layerBacked) { + if (![_tintColor isEqual:color]) { + _tintColor = color; + + if (_loaded(self)) { // Tint color has changed. Unlock here before calling subclasses and exit-early __instanceLock__.unlock(); [self tintColorDidChange]; return; } - } else { - _setToViewOnly(tintColor, color); } } else { - if (_flags.layerBacked) { - _tintColor = color; - } else { - ASDisplayNodeGetPendingState(self).tintColor = color; - } + _setToViewOnly(tintColor, color); } __instanceLock__.unlock(); }