diff --git a/Source/ASDisplayNode.mm b/Source/ASDisplayNode.mm index ccad49b33..afa39b224 100644 --- a/Source/ASDisplayNode.mm +++ b/Source/ASDisplayNode.mm @@ -438,36 +438,43 @@ - (void)onDidLoad:(ASDisplayNodeDidLoadBlock)body - (void)asyncTraitCollectionDidChangeWithPreviousTraitCollection:(ASPrimitiveTraitCollection)previousTraitCollection { if (@available(iOS 13.0, *)) { + // When changing between light and dark mode, often the entire node needs to re-render. + // This change doesn't happen frequently so it's fairly safe to render nodes again __instanceLock__.lock(); - if (self.primitiveTraitCollection.userInterfaceStyle != previousTraitCollection.userInterfaceStyle) { - // When changing between light and dark mode, often the entire node needs to re-render. - // This change doesn't happen frequently so it's fairly safe to render nodes again - BOOL needsClippingCornerUpdate = NO; - CGFloat cornerRadius = _cornerRadius; - ASCornerRoundingType cornerRoundingType = _cornerRoundingType; - UIColor *backgroundColor = _backgroundColor; - if (_loaded(self)) { - CGColorRef cgBackgroundColor = backgroundColor.CGColor; - if (!CGColorEqualToColor(_layer.backgroundColor, cgBackgroundColor)) { - // Background colors do not dynamically update for layer backed nodes since they utilize CGColorRef - // instead of UIColor. Non layer backed node also receive color to the layer (see [_ASPendingState -applyToView:withSpecialPropertiesHandling:]). - // We utilize the _backgroundColor instance variable to track the full dynamic color - // and apply any changes here when trait collection updates occur. - _layer.backgroundColor = cgBackgroundColor; - } - // If we have clipping corners, re-render the clipping corner layer upon user interface style change - if (cornerRoundingType == ASCornerRoundingTypeClipping && cornerRadius > 0.0f) { - needsClippingCornerUpdate = YES; - } - } - __instanceLock__.unlock(); - if (needsClippingCornerUpdate) { - [self _updateClipCornerLayerContentsWithRadius:cornerRadius backgroundColor:backgroundColor]; + BOOL loaded = _loaded(self); + ASPrimitiveTraitCollection primitiveTraitCollection = _primitiveTraitCollection; + __instanceLock__.unlock(); + if (primitiveTraitCollection.userInterfaceStyle != previousTraitCollection.userInterfaceStyle) { + if (loaded) { + // we need to run that on main thread, cause accessing CALayer properties. + // It seems than in iOS 13 sometimes it causes deadlock. + ASPerformBlockOnMainThread(^{ + __instanceLock__.lock(); + CGFloat cornerRadius = _cornerRadius; + ASCornerRoundingType cornerRoundingType = _cornerRoundingType; + UIColor *backgroundColor = _backgroundColor; + ASPrimitiveTraitCollection primitiveTraitCollection = _primitiveTraitCollection; + __instanceLock__.unlock(); + UITraitCollection *traitCollection = ASPrimitiveTraitCollectionToUITraitCollection(primitiveTraitCollection); + UIColor *resolvedBackgroundColor = [backgroundColor resolvedColorWithTraitCollection:traitCollection]; + CGColorRef cgBackgroundColor = resolvedBackgroundColor.CGColor; + if (!CGColorEqualToColor(_layer.backgroundColor, cgBackgroundColor)) { + // Background colors do not dynamically update for layer backed nodes since they utilize CGColorRef + // instead of UIColor. Non layer backed node also receive color to the layer (see [_ASPendingState -applyToView:withSpecialPropertiesHandling:]). + // We utilize the _backgroundColor instance variable to track the full dynamic color + // and apply any changes here when trait collection updates occur. + _layer.backgroundColor = cgBackgroundColor; + } + + // If we have clipping corners, re-render the clipping corner layer upon user interface style change + if (cornerRoundingType == ASCornerRoundingTypeClipping && cornerRadius > 0.0f) { + [self _updateClipCornerLayerContentsWithRadius:cornerRadius backgroundColor:backgroundColor]; + } + + [self setNeedsDisplay]; + }); } - [self setNeedsDisplay]; - return; } - __instanceLock__.unlock(); } }