Skip to content

Commit e95faad

Browse files
Ahamed-AliPureWeen
authored andcommitted
[iOS] Fixed the App crashes when navigating to a page containing a map more than once (#29369)
* Committed the test case and sample * committed the fix * Modified the test sample * Updated the Test condition for windows * Removed unwanted spaces * Optimized the fix * Change the code into modern c#
1 parent 514bcc0 commit e95faad

File tree

5 files changed

+148
-2
lines changed

5 files changed

+148
-2
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
using Microsoft.Maui.Maps;
2+
3+
namespace Maui.Controls.Sample.Issues;
4+
5+
[Issue(IssueTracker.Github, 20612, "Disconnecting Map Handler causes Map to crash on second page entrance and moving to region.", PlatformAffected.iOS | PlatformAffected.macOS)]
6+
public class Issue20612 : TestNavigationPage
7+
{
8+
protected override void Init()
9+
{
10+
PushAsync(new Issue20612page1());
11+
}
12+
}
13+
14+
public class Issue20612page1 : ContentPage
15+
{
16+
public Issue20612page1()
17+
{
18+
var openMapButton = new Button
19+
{
20+
Text = "Navigate to Map page",
21+
HorizontalOptions = LayoutOptions.Center,
22+
VerticalOptions = LayoutOptions.Center,
23+
AutomationId = "MapButton"
24+
};
25+
26+
openMapButton.Clicked += (s, e) =>
27+
{
28+
Navigation.PushAsync(new Issue20612page2());
29+
};
30+
Content = openMapButton;
31+
}
32+
}
33+
34+
public class Issue20612page2 : ContentPage
35+
{
36+
private Microsoft.Maui.Controls.Maps.Map _map;
37+
38+
public Issue20612page2()
39+
{
40+
_map = new Microsoft.Maui.Controls.Maps.Map
41+
{
42+
HorizontalOptions = LayoutOptions.Fill,
43+
VerticalOptions = LayoutOptions.Fill,
44+
BackgroundColor = Colors.Red
45+
};
46+
47+
var goBackButton = new Button
48+
{
49+
Text = "Go back",
50+
HorizontalOptions = LayoutOptions.Center,
51+
VerticalOptions = LayoutOptions.Center,
52+
AutomationId = "GoBackButton"
53+
};
54+
goBackButton.Clicked += GoBack;
55+
56+
var grid = new Grid
57+
{
58+
RowDefinitions =
59+
{
60+
new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }, // Row 0: for map
61+
new RowDefinition { Height = GridLength.Auto } // Row 1: for button
62+
}
63+
};
64+
65+
grid.Children.Add(_map);
66+
Grid.SetRow(_map, 0);
67+
68+
grid.Children.Add(goBackButton);
69+
Grid.SetRow(goBackButton, 1);
70+
Content = grid;
71+
72+
MoveMap();
73+
}
74+
75+
private async void MoveMap()
76+
{
77+
await Task.Delay(1000).ConfigureAwait(false);
78+
79+
MainThread.BeginInvokeOnMainThread(() =>
80+
{
81+
var mapSpan = MapSpan.FromCenterAndRadius(
82+
new Location(5, 5),
83+
Distance.FromMeters(10000));
84+
85+
_map.MoveToRegion(mapSpan);
86+
});
87+
}
88+
89+
void GoBack(object sender, EventArgs e)
90+
{
91+
_map.Handler?.DisconnectHandler();
92+
Navigation.PopAsync();
93+
}
94+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#if TEST_FAILS_ON_WINDOWS
2+
//No Map control support in windows https://learn.microsoft.com/en-us/dotnet/maui/user-interface/controls/map?view=net-maui-9.0
3+
using NUnit.Framework;
4+
using UITest.Appium;
5+
using UITest.Core;
6+
7+
namespace Microsoft.Maui.TestCases.Tests.Issues;
8+
public class Issue20612 : _IssuesUITest
9+
{
10+
public Issue20612(TestDevice device) : base(device) { }
11+
12+
public override string Issue => "Disconnecting Map Handler causes Map to crash on second page entrance and moving to region.";
13+
14+
[Test]
15+
[Category(UITestCategories.Maps)]
16+
public void MapsShouldNotCrashWhenNavigationOccurs()
17+
{
18+
App.WaitForElement("MapButton");
19+
App.Tap("MapButton");
20+
App.WaitForElement("GoBackButton");
21+
App.Tap("GoBackButton");
22+
// second Navigation to Map page
23+
App.WaitForElement("MapButton");
24+
App.Tap("MapButton");
25+
}
26+
}
27+
#endif

src/Core/maps/src/Handlers/Map/MapHandler.iOS.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public partial class MapHandler : ViewHandler<IMap, MauiMKMapView>
1313

1414
protected override MauiMKMapView CreatePlatformView()
1515
{
16-
return MapPool.Get() ?? new MauiMKMapView(this);
16+
return MapPool.Get(this) ?? new MauiMKMapView(this);
1717
}
1818

1919
protected override void ConnectHandler(MauiMKMapView platformView)

src/Core/maps/src/Platform/iOS/MapPool.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Concurrent;
2+
using Microsoft.Maui.Maps.Handlers;
23

34
namespace Microsoft.Maui.Maps.Platform
45
{
@@ -11,6 +12,14 @@ internal class MapPool
1112

1213
public static void Add(MauiMKMapView mapView) => Instance.Maps.Enqueue(mapView);
1314

14-
public static MauiMKMapView? Get() => Instance.Maps.TryDequeue(out MauiMKMapView? mapView) ? mapView : null;
15+
public static MauiMKMapView? Get(IMapHandler mapHandler)
16+
{
17+
if (Instance.Maps.TryDequeue(out MauiMKMapView? mapView) && mapView is not null)
18+
{
19+
mapView.Handler = mapHandler;
20+
return mapView;
21+
}
22+
return null;
23+
}
1524
}
1625
}

src/Core/maps/src/Platform/iOS/MauiMKMapView.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,22 @@ public MauiMKMapView(IMapHandler handler)
2222
OverlayRenderer = GetViewForOverlayDelegate;
2323
}
2424

25+
internal IMapHandler? Handler
26+
{
27+
get
28+
{
29+
_handlerRef.TryGetTarget(out var handler);
30+
return handler;
31+
}
32+
set
33+
{
34+
if (value is not null)
35+
{
36+
_handlerRef = new WeakReference<IMapHandler>(value);
37+
}
38+
}
39+
}
40+
2541
public override void MovedToWindow()
2642
{
2743
base.MovedToWindow();

0 commit comments

Comments
 (0)