diff --git a/src/Controls/tests/DeviceTests/Elements/Border/BorderTests.cs b/src/Controls/tests/DeviceTests/Elements/Border/BorderTests.cs index 4e3d9cb10525..1c981f97c74b 100644 --- a/src/Controls/tests/DeviceTests/Elements/Border/BorderTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/Border/BorderTests.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.Maui.Controls; +using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Controls.Shapes; using Microsoft.Maui.DeviceTests.ImageAnalysis; using Microsoft.Maui.Graphics; @@ -258,6 +259,35 @@ await InvokeOnMainThreadAsync(() => await AssertionExtensions.WaitForGC(handlerReference, platformViewReference); } + + [Fact(DisplayName = "Border With Stroke Shape And Name Does Not Leak")] + public async Task DoesNotLeakWithStrokeShape() + { + SetupBuilder(); + WeakReference platformViewReference = null; + WeakReference handlerReference = null; + + await InvokeOnMainThreadAsync(() => + { + var layout = new Grid(); + var border = new Border(); + var rect = new RoundRectangle(); + border.StrokeShape = rect; + layout.Add(border); + + var nameScope = new NameScope(); + ((INameScope)nameScope).RegisterName("Border", border); + layout.transientNamescope = nameScope; + border.transientNamescope = nameScope; + rect.transientNamescope = nameScope; + + var handler = CreateHandler(layout); + handlerReference = new WeakReference(border.Handler); + platformViewReference = new WeakReference(border.Handler.PlatformView); + }); + + await AssertionExtensions.WaitForGC(handlerReference, platformViewReference); + } [Fact("Ensures the border renders the expected size - Issue 15339")] public async Task BorderAndStrokeIsCorrectSize() diff --git a/src/Core/src/Platform/iOS/MauiCALayer.cs b/src/Core/src/Platform/iOS/MauiCALayer.cs index ddb3c8d67cbf..55f3485b8192 100644 --- a/src/Core/src/Platform/iOS/MauiCALayer.cs +++ b/src/Core/src/Platform/iOS/MauiCALayer.cs @@ -12,8 +12,7 @@ namespace Microsoft.Maui.Platform public class MauiCALayer : CALayer, IAutoSizableCALayer { CGRect _bounds; - [UnconditionalSuppressMessage("Memory", "MEM0002", Justification = "IShape is a non-NSObject in MAUI.")] - IShape? _shape; + WeakReference _shape; UIColor? _backgroundColor; Paint? _background; @@ -36,6 +35,7 @@ public class MauiCALayer : CALayer, IAutoSizableCALayer public MauiCALayer() { _bounds = new CGRect(); + _shape = new WeakReference(null); ContentsScale = UIScreen.MainScreen.Scale; } @@ -98,7 +98,7 @@ public override void DrawInContext(CGContext ctx) public void SetBorderShape(IShape? shape) { - _shape = shape; + _shape = new WeakReference(shape); SetNeedsDisplay(); } @@ -306,10 +306,10 @@ public void SetBorderLineCap(LineCap lineCap) CGPath? GetClipPath() { - if (_shape != null) + if (_shape.TryGetTarget(out var shape)) { var bounds = _bounds.ToRectangle(); - var path = _shape.PathForBounds(bounds); + var path = shape.PathForBounds(bounds); return path?.AsCGPath(); }