[iOS] ListView should not explicitly remove subviews coming from renderers (#1307)

* Add repro for 60563

* [iOS} ListView should not explicitly remove subviews coming from renderers
This commit is contained in:
Samantha Houts 2017-11-29 11:21:18 -08:00 коммит произвёл Rui Marinho
Родитель 2f84a94360
Коммит cda1496271
3 изменённых файлов: 105 добавлений и 3 удалений

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

@ -0,0 +1,92 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
using System.Collections.Generic;
#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
#endif
namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Bugzilla, 60563, "ActivityIndicator in ListView causes SIGSEGV crash in iOS 8", PlatformAffected.iOS)]
public class Bugzilla60563 : TestNavigationPage
{
const string btnGoToList = "btnGoToList";
const string spinner = "spinner";
protected override void Init()
{
Navigation.PushAsync(new NavigationPage(new StartPage()));
}
[Preserve(AllMembers = true)]
class ListPage : ContentPage
{
public ListPage()
{
Title = "List";
Content = new ListView
{
HasUnevenRows = false,
RowHeight = 50,
ItemTemplate = new DataTemplate(() => { return new SpinnerViewCell(); }),
ItemsSource = new List<int> { 1, 2, 3, 4, 5 },
};
}
}
[Preserve(AllMembers = true)]
class SpinnerViewCell : ViewCell
{
public SpinnerViewCell()
{
var indicator = new ActivityIndicator
{
IsRunning = true,
AutomationId = spinner
};
var layout = new RelativeLayout();
layout.Children.Add(indicator, x: () => 0, y: () => 0);
View = indicator;
}
}
[Preserve(AllMembers = true)]
class StartPage : ContentPage
{
public StartPage()
{
var button = new Button
{
Text = "Go To List",
BackgroundColor = Color.Beige,
HeightRequest = 40,
WidthRequest = 100,
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.Center,
AutomationId = btnGoToList
};
button.Clicked += (sender, e) => Navigation.PushAsync(new ListPage());
Title = "Home";
Content = new StackLayout { Children = { new Label { Text = "Click the button to go to a ListView with an ActivityIndicator, then go back to this page. If the app does not crash, this test has passed." }, button } };
}
}
#if UITEST && __IOS__
[Test]
public void Bugzilla60563Test()
{
RunningApp.WaitForElement(q => q.Marked(btnGoToList));
RunningApp.Tap(q => q.Marked(btnGoToList));
RunningApp.WaitForElement(q => q.Marked(spinner));
RunningApp.Back();
RunningApp.WaitForElement(q => q.Marked(btnGoToList));
RunningApp.Tap(q => q.Marked(btnGoToList));
RunningApp.WaitForElement(q => q.Marked(spinner));
}
#endif
}
}

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

@ -226,6 +226,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla59863_0.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla59863_1.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla59863_2.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla60563.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ButtonBackgroundColorTest.cs" />
<Compile Include="$(MSBuildThisFileDirectory)CarouselAsync.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla34561.cs" />

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

@ -102,10 +102,19 @@ namespace Xamarin.Forms.Platform.iOS
void DisposeSubviews(UIView view)
{
foreach (UIView subView in view.Subviews)
DisposeSubviews(subView);
var ver = view as IVisualElementRenderer;
if (ver == null)
{
// VisualElementRenderers should implement their own dispose methods that will appropriately dispose and remove their child views.
// Attempting to do this work twice could cause a SIGSEGV (only observed in iOS8), so don't do this work here.
// Non-renderer views, such as separator lines, etc., can be removed here.
foreach (UIView subView in view.Subviews)
DisposeSubviews(subView);
view.RemoveFromSuperview();
}
view.RemoveFromSuperview();
view.Dispose();
}