diff --git a/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.cs b/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.cs index 77cc6e9eb48a..db0112eb98cc 100644 --- a/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.cs @@ -298,15 +298,19 @@ public async Task DoesNotLeak() await CreateHandlerAndAddToWindow(new Window(navPage), async (handler) => { - var page = new ContentPage { Title = "Page 2" }; + var page = new ContentPage { Title = "Page 2", Content = new VerticalStackLayout { new Label() } }; pageReference = new WeakReference(page); await navPage.Navigation.PushAsync(page); await navPage.Navigation.PopAsync(); }); - await Task.Yield(); - GC.Collect(); - GC.WaitForPendingFinalizers(); + // 3 GCs were required in Android API 23, 2 worked otherwise + for (int i = 0; i < 3; i++) + { + await Task.Yield(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + } Assert.NotNull(pageReference); Assert.False(pageReference.IsAlive, "Page should not be alive!"); diff --git a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs index 4f9c662d01ed..219a72575686 100644 --- a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs @@ -932,7 +932,7 @@ await CreateHandlerAndAddToWindow(shell, async (handler) => { await OnLoadedAsync(shell.CurrentPage); - var page = new ContentPage { Title = "Page 2" }; + var page = new ContentPage { Title = "Page 2", Content = new VerticalStackLayout { new Label() } }; pageReference = new WeakReference(page); await shell.Navigation.PushAsync(page); diff --git a/src/Core/src/Handlers/Layout/LayoutHandler.iOS.cs b/src/Core/src/Handlers/Layout/LayoutHandler.iOS.cs index 3528f617b513..8023623c97b4 100644 --- a/src/Core/src/Handlers/Layout/LayoutHandler.iOS.cs +++ b/src/Core/src/Handlers/Layout/LayoutHandler.iOS.cs @@ -14,13 +14,7 @@ protected override LayoutView CreatePlatformView() throw new InvalidOperationException($"{nameof(VirtualView)} must be set to create a LayoutViewGroup"); } - var view = new LayoutView - { - CrossPlatformMeasure = VirtualView.CrossPlatformMeasure, - CrossPlatformArrange = VirtualView.CrossPlatformArrange, - }; - - return view; + return new(); } public override void SetVirtualView(IView view) @@ -32,8 +26,6 @@ public override void SetVirtualView(IView view) _ = MauiContext ?? throw new InvalidOperationException($"{nameof(MauiContext)} should have been set by base class."); PlatformView.View = view; - PlatformView.CrossPlatformMeasure = VirtualView.CrossPlatformMeasure; - PlatformView.CrossPlatformArrange = VirtualView.CrossPlatformArrange; // Remove any previous children PlatformView.ClearSubviews(); diff --git a/src/Core/src/Platform/iOS/LayoutView.cs b/src/Core/src/Platform/iOS/LayoutView.cs index 7620ae6eeebb..db8ff284560d 100644 --- a/src/Core/src/Platform/iOS/LayoutView.cs +++ b/src/Core/src/Platform/iOS/LayoutView.cs @@ -1,4 +1,5 @@ using System; +using System.Drawing; using CoreGraphics; using Microsoft.Maui.Graphics; using UIKit; @@ -15,7 +16,7 @@ public class LayoutView : MauiView // apply to ViewHandlerExtensions.MeasureVirtualView public override CGSize SizeThatFits(CGSize size) { - if (CrossPlatformMeasure == null) + if (View is not ILayout layout) { return base.SizeThatFits(size); } @@ -23,7 +24,7 @@ public override CGSize SizeThatFits(CGSize size) var width = size.Width; var height = size.Height; - var crossPlatformSize = CrossPlatformMeasure(width, height); + var crossPlatformSize = layout.CrossPlatformMeasure(width, height); _measureValid = true; return crossPlatformSize.ToCGSize(); @@ -36,15 +37,20 @@ public override void LayoutSubviews() { base.LayoutSubviews(); + if (View is not ILayout layout) + { + return; + } + var bounds = AdjustForSafeArea(Bounds).ToRectangle(); if (!_measureValid) { - CrossPlatformMeasure?.Invoke(bounds.Width, bounds.Height); + layout.CrossPlatformMeasure(bounds.Width, bounds.Height); _measureValid = true; } - CrossPlatformArrange?.Invoke(bounds); + layout.CrossPlatformArrange(bounds); } public override void SetNeedsLayout() @@ -68,9 +74,6 @@ public override void WillRemoveSubview(UIView uiview) Superview?.SetNeedsLayout(); } - internal Func? CrossPlatformMeasure { get; set; } - internal Func? CrossPlatformArrange { get; set; } - public override UIView HitTest(CGPoint point, UIEvent? uievent) { var result = base.HitTest(point, uievent); diff --git a/src/Core/src/Platform/iOS/MauiView.cs b/src/Core/src/Platform/iOS/MauiView.cs index 23cde6159e31..6dcce95793c6 100644 --- a/src/Core/src/Platform/iOS/MauiView.cs +++ b/src/Core/src/Platform/iOS/MauiView.cs @@ -1,4 +1,5 @@ -using CoreGraphics; +using System; +using CoreGraphics; using ObjCRuntime; using UIKit; @@ -8,7 +9,13 @@ public abstract class MauiView : UIView { static bool? _respondsToSafeArea; - public IView? View { get; set; } + WeakReference? _reference; + + public IView? View + { + get => _reference != null && _reference.TryGetTarget(out var v) ? v : null; + set => _reference = value == null ? null : new(value); + } bool RespondsToSafeArea() {