From ab8d453e7a558b86178022cfe5df5d5d6e174182 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Mon, 14 Oct 2024 14:30:03 -0700 Subject: [PATCH] fix(iOS): Replace uses of `CGColorRef` with UIColor to avoid manual memory management v2 (#47019) Summary: NOTE: This code is largely the same as https://github.com/facebook/react-native/pull/46847, I am merely fixing some internal issues The original diff (D63989547) was backed out because it was causing some crashes related to some internal code that had to be changed. That code did not necessarily need to be changed - we could have just left the `RCTCreateCGColorRefFromSharedColor` function and not touched the internal code - which is what I am going to do here Changelog: [Internal] Differential Revision: D64201626 --- .../View/RCTViewComponentView.mm | 45 +++++++------------ .../React/Views/RCTBorderDrawing.h | 10 ++--- .../React/Views/RCTBorderDrawing.m | 42 +++++++++-------- packages/react-native/React/Views/RCTView.m | 19 ++++---- 4 files changed, 49 insertions(+), 67 deletions(-) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 04b2ede4f96c..87983b0dbc13 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -242,9 +242,8 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & // `shadowColor` if (oldViewProps.shadowColor != newViewProps.shadowColor) { - CGColorRef shadowColor = RCTCreateCGColorRefFromSharedColor(newViewProps.shadowColor); - self.layer.shadowColor = shadowColor; - CGColorRelease(shadowColor); + UIColor *shadowColor = RCTUIColorFromSharedColor(newViewProps.shadowColor); + self.layer.shadowColor = shadowColor.CGColor; needsInvalidateLayer = YES; } @@ -682,7 +681,7 @@ static void RCTAddContourEffectToLayer( const RCTBorderStyle &contourStyle) { UIImage *image = RCTGetBorderImage( - contourStyle, layer.bounds.size, cornerRadii, contourInsets, contourColors, [UIColor clearColor].CGColor, NO); + contourStyle, layer.bounds.size, cornerRadii, contourInsets, contourColors, [UIColor clearColor], NO); if (image == nil) { layer.contents = nil; @@ -711,18 +710,10 @@ static void RCTAddContourEffectToLayer( static RCTBorderColors RCTCreateRCTBorderColorsFromBorderColors(BorderColors borderColors) { return RCTBorderColors{ - .top = RCTCreateCGColorRefFromSharedColor(borderColors.top), - .left = RCTCreateCGColorRefFromSharedColor(borderColors.left), - .bottom = RCTCreateCGColorRefFromSharedColor(borderColors.bottom), - .right = RCTCreateCGColorRefFromSharedColor(borderColors.right)}; -} - -static void RCTReleaseRCTBorderColors(RCTBorderColors borderColors) -{ - CGColorRelease(borderColors.top); - CGColorRelease(borderColors.left); - CGColorRelease(borderColors.bottom); - CGColorRelease(borderColors.right); + .top = RCTUIColorFromSharedColor(borderColors.top), + .left = RCTUIColorFromSharedColor(borderColors.left), + .bottom = RCTUIColorFromSharedColor(borderColors.bottom), + .right = RCTUIColorFromSharedColor(borderColors.right)}; } static CALayerCornerCurve CornerCurveFromBorderCurve(BorderCurve borderCurve) @@ -870,7 +861,7 @@ - (void)invalidateLayer (*borderMetrics.borderColors.left).getUIColor() != nullptr)); // background color - CGColorRef backgroundColor = [_backgroundColor resolvedColorWithTraitCollection:self.traitCollection].CGColor; + UIColor *backgroundColor = [_backgroundColor resolvedColorWithTraitCollection:self.traitCollection]; // The reason we sometimes do not set self.layer's backgroundColor is because // we want to support non-uniform border radii, which apple does not natively // support. To get this behavior we need to create a CGPath in the shape that @@ -880,7 +871,7 @@ - (void)invalidateLayer if (useCoreAnimationBorderRendering) { [_backgroundColorLayer removeFromSuperlayer]; _backgroundColorLayer = nil; - layer.backgroundColor = backgroundColor; + layer.backgroundColor = backgroundColor.CGColor; } else { layer.backgroundColor = nil; if (!_backgroundColorLayer) { @@ -890,7 +881,7 @@ - (void)invalidateLayer [self.layer addSublayer:_backgroundColorLayer]; } - _backgroundColorLayer.backgroundColor = backgroundColor; + _backgroundColorLayer.backgroundColor = backgroundColor.CGColor; if (borderMetrics.borderRadii.isUniform()) { _backgroundColorLayer.mask = nil; _backgroundColorLayer.cornerRadius = borderMetrics.borderRadii.topLeft.horizontal; @@ -911,9 +902,8 @@ - (void)invalidateLayer _borderLayer = nil; layer.borderWidth = (CGFloat)borderMetrics.borderWidths.left; - CGColorRef borderColor = RCTCreateCGColorRefFromSharedColor(borderMetrics.borderColors.left); - layer.borderColor = borderColor; - CGColorRelease(borderColor); + UIColor *borderColor = RCTUIColorFromSharedColor(borderMetrics.borderColors.left); + layer.borderColor = borderColor.CGColor; layer.cornerRadius = (CGFloat)borderMetrics.borderRadii.topLeft.horizontal; layer.cornerCurve = CornerCurveFromBorderCurve(borderMetrics.borderCurves.topLeft); } else { @@ -938,8 +928,6 @@ - (void)invalidateLayer borderColors, RCTUIEdgeInsetsFromEdgeInsets(borderMetrics.borderWidths), RCTBorderStyleFromBorderStyle(borderMetrics.borderStyles.left)); - - RCTReleaseRCTBorderColors(borderColors); } // outline @@ -958,12 +946,11 @@ - (void)invalidateLayer layer.bounds, -_props->outlineOffset - _props->outlineWidth, -_props->outlineOffset - _props->outlineWidth); if (borderMetrics.borderRadii.isUniform() && borderMetrics.borderRadii.topLeft.horizontal == 0) { - CGColorRef outlineColor = RCTCreateCGColorRefFromSharedColor(_props->outlineColor); + UIColor *outlineColor = RCTUIColorFromSharedColor(_props->outlineColor); _outlineLayer.borderWidth = _props->outlineWidth; - _outlineLayer.borderColor = outlineColor; - CGColorRelease(outlineColor); + _outlineLayer.borderColor = outlineColor.CGColor; } else { - CGColorRef outlineColor = RCTCreateCGColorRefFromSharedColor(_props->outlineColor); + UIColor *outlineColor = RCTUIColorFromSharedColor(_props->outlineColor); RCTAddContourEffectToLayer( _outlineLayer, @@ -971,8 +958,6 @@ - (void)invalidateLayer RCTBorderColors{outlineColor, outlineColor, outlineColor, outlineColor}, UIEdgeInsets{_props->outlineWidth, _props->outlineWidth, _props->outlineWidth, _props->outlineWidth}, RCTBorderStyleFromOutlineStyle(_props->outlineStyle)); - - CGColorRelease(outlineColor); } } diff --git a/packages/react-native/React/Views/RCTBorderDrawing.h b/packages/react-native/React/Views/RCTBorderDrawing.h index 39105666f63d..b13ffdf6fbad 100644 --- a/packages/react-native/React/Views/RCTBorderDrawing.h +++ b/packages/react-native/React/Views/RCTBorderDrawing.h @@ -29,10 +29,10 @@ typedef struct { } RCTCornerInsets; typedef struct { - CGColorRef top; - CGColorRef left; - CGColorRef bottom; - CGColorRef right; + UIColor *top; + UIColor *left; + UIColor *bottom; + UIColor *right; } RCTBorderColors; /** @@ -67,5 +67,5 @@ RCT_EXTERN UIImage *RCTGetBorderImage( RCTCornerRadii cornerRadii, UIEdgeInsets borderInsets, RCTBorderColors borderColors, - CGColorRef backgroundColor, + UIColor *backgroundColor, BOOL drawToEdge); diff --git a/packages/react-native/React/Views/RCTBorderDrawing.m b/packages/react-native/React/Views/RCTBorderDrawing.m index 67bf10cba935..b51499af33d0 100644 --- a/packages/react-native/React/Views/RCTBorderDrawing.m +++ b/packages/react-native/React/Views/RCTBorderDrawing.m @@ -30,9 +30,9 @@ BOOL RCTCornerRadiiAreEqualAndSymmetrical(RCTCornerRadii cornerRadii) BOOL RCTBorderColorsAreEqual(RCTBorderColors borderColors) { - return CGColorEqualToColor(borderColors.left, borderColors.right) && - CGColorEqualToColor(borderColors.left, borderColors.top) && - CGColorEqualToColor(borderColors.left, borderColors.bottom); + return CGColorEqualToColor(borderColors.left.CGColor, borderColors.right.CGColor) && + CGColorEqualToColor(borderColors.left.CGColor, borderColors.top.CGColor) && + CGColorEqualToColor(borderColors.left.CGColor, borderColors.bottom.CGColor); } RCTCornerInsets RCTGetCornerInsets(RCTCornerRadii cornerRadii, UIEdgeInsets edgeInsets) @@ -182,9 +182,9 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn } static UIGraphicsImageRenderer * -RCTMakeUIGraphicsImageRenderer(CGSize size, CGColorRef backgroundColor, BOOL hasCornerRadii, BOOL drawToEdge) +RCTMakeUIGraphicsImageRenderer(CGSize size, UIColor *backgroundColor, BOOL hasCornerRadii, BOOL drawToEdge) { - const CGFloat alpha = CGColorGetAlpha(backgroundColor); + const CGFloat alpha = CGColorGetAlpha(backgroundColor.CGColor); const BOOL opaque = (drawToEdge || !hasCornerRadii) && alpha == 1.0; UIGraphicsImageRendererFormat *const rendererFormat = [UIGraphicsImageRendererFormat defaultFormat]; rendererFormat.opaque = opaque; @@ -197,7 +197,7 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn CGSize viewSize, UIEdgeInsets borderInsets, RCTBorderColors borderColors, - CGColorRef backgroundColor, + UIColor *backgroundColor, BOOL drawToEdge) { const BOOL hasCornerRadii = RCTCornerRadiiAreAboveThreshold(cornerRadii); @@ -233,18 +233,16 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn UIGraphicsImageRenderer *const imageRenderer = RCTMakeUIGraphicsImageRenderer(size, backgroundColor, hasCornerRadii, drawToEdge); - CGColorRetain(backgroundColor); UIImage *image = [imageRenderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull rendererContext) { const CGContextRef context = rendererContext.CGContext; const CGRect rect = {.size = size}; CGPathRef path = RCTPathCreateOuterOutline(drawToEdge, rect, cornerRadii); if (backgroundColor) { - CGContextSetFillColorWithColor(context, backgroundColor); + CGContextSetFillColorWithColor(context, backgroundColor.CGColor); CGContextAddPath(context, path); CGContextFillPath(context); } - CGColorRelease(backgroundColor); CGContextAddPath(context, path); CGPathRelease(path); @@ -256,7 +254,7 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn BOOL hasEqualColors = RCTBorderColorsAreEqual(borderColors); if ((drawToEdge || !hasCornerRadii) && hasEqualColors) { - CGContextSetFillColorWithColor(context, borderColors.left); + CGContextSetFillColorWithColor(context, borderColors.left.CGColor); CGContextAddRect(context, rect); CGContextAddPath(context, insetPath); CGContextEOFillPath(context); @@ -321,7 +319,7 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn } } - CGColorRef currentColor = NULL; + UIColor *currentColor = nil; // RIGHT if (borderInsets.right > 0) { @@ -345,8 +343,8 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn (CGPoint){size.width, size.height}, }; - if (!CGColorEqualToColor(currentColor, borderColors.bottom)) { - CGContextSetFillColorWithColor(context, currentColor); + if (!CGColorEqualToColor(currentColor.CGColor, borderColors.bottom.CGColor)) { + CGContextSetFillColorWithColor(context, currentColor.CGColor); CGContextFillPath(context); currentColor = borderColors.bottom; } @@ -362,8 +360,8 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn (CGPoint){0, size.height}, }; - if (!CGColorEqualToColor(currentColor, borderColors.left)) { - CGContextSetFillColorWithColor(context, currentColor); + if (!CGColorEqualToColor(currentColor.CGColor, borderColors.left.CGColor)) { + CGContextSetFillColorWithColor(context, currentColor.CGColor); CGContextFillPath(context); currentColor = borderColors.left; } @@ -379,15 +377,15 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn (CGPoint){size.width, 0}, }; - if (!CGColorEqualToColor(currentColor, borderColors.top)) { - CGContextSetFillColorWithColor(context, currentColor); + if (!CGColorEqualToColor(currentColor.CGColor, borderColors.top.CGColor)) { + CGContextSetFillColorWithColor(context, currentColor.CGColor); CGContextFillPath(context); currentColor = borderColors.top; } CGContextAddLines(context, points, sizeof(points) / sizeof(*points)); } - CGContextSetFillColorWithColor(context, currentColor); + CGContextSetFillColorWithColor(context, currentColor.CGColor); CGContextFillPath(context); } @@ -467,7 +465,7 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn CGSize viewSize, UIEdgeInsets borderInsets, RCTBorderColors borderColors, - CGColorRef backgroundColor, + UIColor *backgroundColor, BOOL drawToEdge) { NSCParameterAssert(borderStyle == RCTBorderStyleDashed || borderStyle == RCTBorderStyleDotted); @@ -494,7 +492,7 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn CGContextAddPath(context, outerPath); CGPathRelease(outerPath); - CGContextSetFillColorWithColor(context, backgroundColor); + CGContextSetFillColorWithColor(context, backgroundColor.CGColor); CGContextFillPath(context); } @@ -513,7 +511,7 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor); CGContextAddPath(context, path); - CGContextSetStrokeColorWithColor(context, borderColors.top); + CGContextSetStrokeColorWithColor(context, borderColors.top.CGColor); CGContextStrokePath(context); CGPathRelease(path); @@ -526,7 +524,7 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn RCTCornerRadii cornerRadii, UIEdgeInsets borderInsets, RCTBorderColors borderColors, - CGColorRef backgroundColor, + UIColor *backgroundColor, BOOL drawToEdge) { switch (borderStyle) { diff --git a/packages/react-native/React/Views/RCTView.m b/packages/react-native/React/Views/RCTView.m index 8602dedc50df..b07e7ef9e54b 100644 --- a/packages/react-native/React/Views/RCTView.m +++ b/packages/react-native/React/Views/RCTView.m @@ -774,10 +774,10 @@ - (RCTBorderColors)borderColorsWithTraitCollection:(UITraitCollection *)traitCol [directionAwareBorderRightColor resolvedColorWithTraitCollection:self.traitCollection]; return (RCTBorderColors){ - (borderTopColor ?: borderColor).CGColor, - (directionAwareBorderLeftColor ?: borderColor).CGColor, - (borderBottomColor ?: borderColor).CGColor, - (directionAwareBorderRightColor ?: borderColor).CGColor, + (borderTopColor ?: borderColor), + (directionAwareBorderLeftColor ?: borderColor), + (borderBottomColor ?: borderColor), + (directionAwareBorderRightColor ?: borderColor), }; } @@ -814,21 +814,20 @@ - (void)displayLayer:(CALayer *)layer // the content. For this reason, only use iOS border drawing when clipping // or when the border is hidden. - (borderInsets.top == 0 || (borderColors.top && CGColorGetAlpha(borderColors.top) == 0) || self.clipsToBounds); + (borderInsets.top == 0 || (borderColors.top && CGColorGetAlpha(borderColors.top.CGColor) == 0) || + self.clipsToBounds); // iOS clips to the outside of the border, but CSS clips to the inside. To // solve this, we'll need to add a container view inside the main view to // correctly clip the subviews. - CGColorRef backgroundColor; - - backgroundColor = [_backgroundColor resolvedColorWithTraitCollection:self.traitCollection].CGColor; + UIColor *backgroundColor = [_backgroundColor resolvedColorWithTraitCollection:self.traitCollection]; if (useIOSBorderRendering) { layer.cornerRadius = cornerRadii.topLeftHorizontal; - layer.borderColor = borderColors.left; + layer.borderColor = borderColors.left.CGColor; layer.borderWidth = borderInsets.left; - layer.backgroundColor = backgroundColor; + layer.backgroundColor = backgroundColor.CGColor; layer.contents = nil; layer.needsDisplayOnBoundsChange = NO; layer.mask = nil;