Skip to content

Commit

Permalink
[iOS] Crash upon resuming the app - fix (dotnet#23360)
Browse files Browse the repository at this point in the history
* [iOS] Crash upon resuming the app - fix (dotnet#21948)

* Refactor

* Update UIApplicationExtensions.cs

* Update UIApplicationExtensions.cs

* Update UIApplicationExtensions.cs

* Added a UI test (dotnet#21948)

* Added a test category (dotnet#23428)

* remove "'"

---------

Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
  • Loading branch information
kubaflo and PureWeen authored Jul 5, 2024
1 parent 2f5c8dc commit 8d9a1a5
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 2 deletions.
8 changes: 8 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue21948.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.Issues.Issue21948">
<Button Text="Open a new window"
AutomationId="button"
Clicked="OpenNewWindowClicked" />
</ContentPage>
79 changes: 79 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue21948.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Xaml;
using Microsoft.Maui.Platform;
using Microsoft.Maui;
using System.Linq;
using System;
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Xaml;
#if IOS || MACCATALYST
using UIKit;
using CoreGraphics;
#endif

namespace Maui.Controls.Sample.Issues
{
[XamlCompilation(XamlCompilationOptions.Compile)]
[Issue(IssueTracker.Github, 21948, "Crash upon resuming the app window was already activated", PlatformAffected.iOS)]
public partial class Issue21948 : ContentPage
{
public Issue21948()
{
InitializeComponent();
}

public void OpenNewWindowClicked(object obj, EventArgs e)
{
#if IOS || MACCATALYST
OpenNewWindow();
#endif
}

#if IOS || MACCATALYST
async void OpenNewWindow()
{
var uIWindow = new UIWindow();
var keyWindow = (this.Window.Handler.PlatformView as UIWindow);
if (keyWindow?.WindowLevel == UIWindowLevel.Normal)
keyWindow.WindowLevel = -1;

var page = new ContentPage();
this.AddLogicalChild(page);
var handler = page.ToHandler(this.Handler.MauiContext);

uIWindow.RootViewController = new UIViewController();
uIWindow.WindowLevel = UIWindowLevel.Normal;
uIWindow.MakeKeyAndVisible();

// Simulate backgrounding the app
nint taskId = UIApplication.BackgroundTaskInvalid;
taskId = UIApplication.SharedApplication.BeginBackgroundTask(() =>
{
UIApplication.SharedApplication.EndBackgroundTask(taskId);
});

// Simulate background time
await Task.Delay(2000);
UIApplication.SharedApplication.EndBackgroundTask(taskId);

var rvc = uIWindow.RootViewController;

if (rvc != null)
{
await rvc.DismissViewControllerAsync(false);
rvc.Dispose();
}

// Simulate bringing the app back to the foreground
await Task.Delay(1000);

uIWindow.RootViewController = null;
uIWindow.Hidden = true;
keyWindow.WindowLevel = UIWindowLevel.Normal;
this.RemoveLogicalChild(page);
}
#endif
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#if IOS || MACCATALYST
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class Issue21948 : _IssuesUITest
{
public Issue21948(TestDevice device) : base(device) { }

public override string Issue => "Crash upon resuming the app window was already activated";

[Test]
[Category(UITestCategories.Window)]
public void OpenAlertWithModals()
{
App.WaitForElement("button");
App.Click("button");

// The test passes if no exception is thrown
App.WaitForElement("button");
}
}
}
#endif
31 changes: 29 additions & 2 deletions src/Core/src/Platform/iOS/UIApplicationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,35 @@ internal static UIEdgeInsets GetSafeAreaInsetsForWindow(this UIApplication appli
return null;
}

public static IWindow? GetWindow(this UIApplication application) =>
application.GetKeyWindow().GetWindow();
public static IWindow? GetWindow(this UIApplication application)
{
// If there's only one window to return then just return that window
var windows = IPlatformApplication.Current?.Application?.Windows ?? Array.Empty<IWindow>();

if (windows.Count == 1)
return windows[0];

if (OperatingSystem.IsIOSVersionAtLeast(13))
{
foreach(var windowScene in application.ConnectedScenes)
{
if (windowScene is UIWindowScene uiWindowScene)
{
if(uiWindowScene.Windows.Length == 1 && uiWindowScene.Windows[0].GetWindow() is IWindow window)
{
return window;
}
}
}
}
else
{
if(application.Windows.Length == 1)
return application.Windows[0].GetWindow();
}

return application.GetKeyWindow().GetWindow();
}

public static IWindow? GetWindow(this UIWindow? platformWindow)
{
Expand Down

0 comments on commit 8d9a1a5

Please sign in to comment.