Remove controller from UINavigationController stack when page is removed (#10140)

* Remove controller from UINavigationController stack  when page is removed

* - add uitest

* - remove extra code
This commit is contained in:
Shane Neuville 2020-04-02 10:21:40 -06:00 коммит произвёл GitHub
Родитель 08a7853ee2
Коммит e5b02c20b4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 101 добавлений и 15 удалений

Просмотреть файл

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
using System.Threading.Tasks;
#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
using Xamarin.Forms.Core.UITests;
#endif
namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 6484, "[iOS] Shell - Go back two pages crashes the app with a NullReferenceException",
PlatformAffected.iOS)]
#if UITEST
[NUnit.Framework.Category(UITestCategories.Shell)]
#endif
public class Issue6484 : TestShell
{
StackLayout layout = null;
ContentPage page = null;
protected override void Init()
{
layout = new StackLayout();
page = new ContentPage()
{
Content = layout
};
page.Appearing += OnPageAppearing;
AddContentPage(page);
}
async void OnPageAppearing(object sender, EventArgs e)
{
page.Appearing -= OnPageAppearing;
var removeMe = new ContentPage();
await Navigation.PushAsync(removeMe);
await Navigation.PushAsync(new ContentPage());
await Task.Delay(1);
Navigation.RemovePage(removeMe);
await Navigation.PopAsync();
await Task.Delay(1);
layout.Children.Add(
new Label()
{
Text = "If app hasn't crashed test has succeeded",
AutomationId = "Success"
});
}
#if UITEST
[Test]
public void RemovingIntermediatePagesBreaksShell()
{
RunningApp.WaitForElement("Success");
}
#endif
}
}

Просмотреть файл

@ -10,6 +10,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)CollectionViewGroupTypeIssue.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue6484.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue6187.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3228.xaml.cs">
<DependentUpon>Issue3228.xaml</DependentUpon>
@ -1460,12 +1461,12 @@
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue9735.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
<SubType>Designer</SubType>
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue9305.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
<SubType>Designer</SubType>
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue9588.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>

Просмотреть файл

@ -724,20 +724,22 @@ namespace Xamarin.Forms
bool currentPage = (((IShellSectionController)this).PresentedPage) == page;
var stack = _navStack.ToList();
stack.Remove(page);
var allow = ((IShellController)Shell).ProposeNavigation(
ShellNavigationSource.Remove,
ShellItem,
this,
CurrentItem,
stack,
true
);
var allow = (!currentPage) ? true :
((IShellController)Shell).ProposeNavigation(
ShellNavigationSource.Remove,
ShellItem,
this,
CurrentItem,
stack,
true
);
if (!allow)
return;
if(currentPage)
PresentedPageDisappearing();
_navStack.Remove(page);
if(currentPage)

Просмотреть файл

@ -336,15 +336,20 @@ namespace Xamarin.Forms.Platform.iOS
var page = e.Page;
var renderer = Platform.GetRenderer(page);
var viewController = renderer?.ViewController;
if (renderer != null)
if (viewController == null && _trackers.ContainsKey(page))
viewController = _trackers[page].ViewController;
if (viewController != null)
{
if (renderer.ViewController == TopViewController)
if (viewController == TopViewController)
{
e.Animated = false;
OnPopRequested(e);
}
ViewControllers = ViewControllers.Remove(renderer.ViewController);
ViewControllers = ViewControllers.Remove(viewController);
DisposePage(page);
}
}
@ -371,10 +376,14 @@ namespace Xamarin.Forms.Platform.iOS
{
if (_trackers.TryGetValue(page, out var tracker))
{
if(tracker.ViewController != null && ViewControllers.Contains(tracker.ViewController))
ViewControllers = ViewControllers.Remove(_trackers[page].ViewController);
tracker.Dispose();
_trackers.Remove(page);
}
var renderer = Platform.GetRenderer(page);
if (renderer != null)
{