[Mac] NavigationPageRenderer amendments RE: Issue4388 (#4607) #4388 #4389

* crash fixes https://github.com/xamarin/Xamarin.Forms/issues/4388

* Subview Z-index fix

* [MacOS] Dispose cleanup

* Added WantsLayer prop to Insert method

* Added disposing check to ViewRenderer
This commit is contained in:
Andrei 2019-02-12 15:33:17 +03:00 коммит произвёл Rui Marinho
Родитель 15c6f561e6
Коммит 334e23d7c6
14 изменённых файлов: 232 добавлений и 154 удалений

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

@ -115,7 +115,7 @@
<Name>Xamarin.Forms.Maps</Name>
</ProjectReference>
<ProjectReference Include="..\Xamarin.Forms.Platform\Xamarin.Forms.Platform.csproj">
<Project>{67F9D3A8-F71E-4428-913F-C37AE82CDB24}</Project>
<Project>{D31A6537-ED9C-4EBD-B231-A8D4FE44126A}</Project>
<Name>Xamarin.Forms.Platform</Name>
</ProjectReference>
<ProjectReference Include="..\Xamarin.Forms.Platform.MacOS\Xamarin.Forms.Platform.MacOS.csproj">

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

@ -41,8 +41,7 @@ namespace Xamarin.Forms.Platform.MacOS
IVisualElementRenderer renderer;
if (_rendererRef != null && _rendererRef.TryGetTarget(out renderer) && renderer.Element != null)
{
Platform.DisposeModelAndChildrenRenderers(renderer.Element);
renderer.Element.DisposeModalAndChildRenderers();
_rendererRef = null;
}
}
@ -99,7 +98,7 @@ namespace Xamarin.Forms.Platform.MacOS
{
//when cells are getting reused the element could be already set to another cell
//so we should dispose based on the renderer and not the renderer.Element
Platform.DisposeRendererAndChildren(renderer);
renderer.Element.DisposeModalAndChildRenderers();
renderer = GetNewRenderer();
}
}

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

@ -66,7 +66,7 @@ namespace Xamarin.Forms.Platform.MacOS
if (disposing)
{
foreach (var modal in _modals)
Platform.DisposeModelAndChildrenRenderers(modal);
modal.DisposeModalAndChildRenderers();
_renderer = null;
}
_disposed = true;
@ -76,7 +76,7 @@ namespace Xamarin.Forms.Platform.MacOS
void HandleChildRemoved(object sender, ElementEventArgs e)
{
var view = e.Element;
Platform.DisposeModelAndChildrenRenderers(view);
view.DisposeModalAndChildRenderers();
}
Task PresentModalAsync(Page modal, bool animated)
@ -124,7 +124,7 @@ namespace Xamarin.Forms.Platform.MacOS
: NSViewControllerTransitionOptions.None;
var task = _renderer.HandleAsyncAnimation(controller, toViewController, option,
() => Platform.DisposeModelAndChildrenRenderers(modal), modal);
() => modal.DisposeModalAndChildRenderers() , modal);
return task;
}
}

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

@ -193,6 +193,32 @@ namespace Xamarin.Forms.Platform.MacOS
}
}
internal void UpdateNavigationItems(bool forceShowBackButton = false)
{
if (_toolbar == null || _navigation == null || _navigationGroup == null)
return;
var items = new List<ToolbarItem>();
if (ShowBackButton(forceShowBackButton))
{
var backButtonItem = new ToolbarItem
{
Text = GetPreviousPageTitle(),
Command = new Command(async () => await NavigateBackFrombackButton())
};
items.Add(backButtonItem);
}
UpdateGroup(_navigationGroup, items, BackButtonItemWidth, -1);
var navItemBack = _navigationGroup.Items.FirstOrDefault();
if (navItemBack != null)
{
navItemBack.Button.Image = NSImage.ImageNamed(NSImageName.GoLeftTemplate);
navItemBack.Button.SizeToFit();
navItemBack.Button.AccessibilityTitle = "NSBackButton";
}
}
void UpdateBarBackgroundColor()
{
var bgColor = GetBackgroundColor().CGColor;
@ -223,12 +249,12 @@ namespace Xamarin.Forms.Platform.MacOS
await popAsyncInner;
}
bool ShowBackButton()
bool ShowBackButton(bool forceShowBackButton)
{
if (_navigation == null)
return false;
return NavigationPage.GetHasBackButton(_navigation.CurrentPage) && !IsRootPage();
return NavigationPage.GetHasBackButton(_navigation.CurrentPage) && (forceShowBackButton || !IsRootPage());
}
bool IsRootPage()
@ -320,32 +346,6 @@ namespace Xamarin.Forms.Platform.MacOS
UpdateGroup(_toolbarGroup, currentPage.ToolbarItems, ToolbarItemWidth, ToolbarItemSpacing);
}
void UpdateNavigationItems()
{
if (_toolbar == null || _navigation == null || _navigationGroup == null)
return;
var items = new List<ToolbarItem>();
if (ShowBackButton())
{
var backButtonItem = new ToolbarItem
{
Text = GetPreviousPageTitle(),
Command = new Command(async () => await NavigateBackFrombackButton())
};
items.Add(backButtonItem);
}
UpdateGroup(_navigationGroup, items, BackButtonItemWidth, -1);
var navItemBack = _navigationGroup.Items.FirstOrDefault();
if (navItemBack != null)
{
navItemBack.Button.Image = NSImage.ImageNamed(NSImageName.GoLeftTemplate);
navItemBack.Button.SizeToFit();
navItemBack.Button.AccessibilityTitle = "NSBackButton";
}
}
void UpdateTabbedItems()
{
if (_toolbar == null || _navigation == null || _tabbedGroup == null)

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

@ -17,7 +17,7 @@ namespace Xamarin.Forms.Platform.MacOS
view.IsPlatformEnabled = newvalue != null;
});
readonly PlatformRenderer PlatformRenderer;
readonly PlatformRenderer _renderer;
bool _appeared;
bool _disposed;
@ -26,12 +26,12 @@ namespace Xamarin.Forms.Platform.MacOS
internal Platform()
{
PlatformRenderer = new PlatformRenderer(this);
_renderer = new PlatformRenderer(this);
MessagingCenter.Subscribe(this, Page.AlertSignalName, (Page sender, AlertArguments arguments) =>
{
var alert = NSAlert.WithMessage(arguments.Title, arguments.Cancel, arguments.Accept, null, arguments.Message);
var result = alert.RunSheetModal(PlatformRenderer.View.Window);
var result = alert.RunSheetModal(_renderer.View.Window);
if (arguments.Accept == null)
arguments.SetResult(result == 1);
else
@ -57,7 +57,7 @@ namespace Xamarin.Forms.Platform.MacOS
alert.Layout();
}
var result = (int)alert.RunSheetModal(PlatformRenderer.View.Window);
var result = (int)alert.RunSheetModal(_renderer.View.Window);
var titleResult = string.Empty;
if (result == 1)
titleResult = arguments.Cancel;
@ -102,8 +102,10 @@ namespace Xamarin.Forms.Platform.MacOS
MessagingCenter.Unsubscribe<Page, AlertArguments>(this, Page.AlertSignalName);
MessagingCenter.Unsubscribe<Page, bool>(this, Page.BusySetSignalName);
DisposeModelAndChildrenRenderers(Page);
PlatformRenderer.Dispose();
Page.DisposeModalAndChildRenderers();
//foreach (var modal in _modals)
//modal.DisposeModalAndChildRenderers();
_renderer.Dispose();
}
public static IVisualElementRenderer CreateRenderer(VisualElement element)
@ -130,50 +132,7 @@ namespace Xamarin.Forms.Platform.MacOS
base.OnBindingContextChanged();
}
internal NSViewController ViewController => PlatformRenderer;
internal static void DisposeModelAndChildrenRenderers(Element view)
{
foreach (VisualElement child in view.Descendants())
DisposeRenderer(child);
DisposeRenderer(view);
}
static void DisposeRenderer(Element view)
{
IVisualElementRenderer renderer = GetRenderer((VisualElement)view);
if (renderer?.ViewController?.ParentViewController != null)
renderer?.ViewController?.RemoveFromParentViewController();
renderer?.NativeView?.RemoveFromSuperview();
renderer?.Dispose();
view.ClearValue(RendererProperty);
}
internal static void DisposeRendererAndChildren(IVisualElementRenderer rendererToRemove)
{
if (rendererToRemove == null || rendererToRemove.Element == null)
return;
if (GetRenderer(rendererToRemove.Element) == rendererToRemove)
rendererToRemove.Element.ClearValue(RendererProperty);
if (rendererToRemove.NativeView != null)
{
var subviews = rendererToRemove.NativeView.Subviews;
for (var i = 0; i < subviews.Length; i++)
{
var childRenderer = subviews[i] as IVisualElementRenderer;
if (childRenderer != null)
DisposeRendererAndChildren(childRenderer);
}
rendererToRemove.NativeView.RemoveFromSuperview();
}
rendererToRemove.Dispose();
}
internal NSViewController ViewController => _renderer;
internal void LayoutSubviews()
{
@ -185,7 +144,7 @@ namespace Xamarin.Forms.Platform.MacOS
if (rootRenderer == null)
return;
rootRenderer.SetElementSize(new Size(PlatformRenderer.View.Bounds.Width, PlatformRenderer.View.Bounds.Height));
rootRenderer.SetElementSize(new Size(_renderer.View.Bounds.Width, _renderer.View.Bounds.Height));
}
internal void SetPage(Page newRoot)
@ -203,14 +162,14 @@ namespace Xamarin.Forms.Platform.MacOS
Page.DescendantRemoved += HandleChildRemoved;
TargetApplication.NavigationProxy.Inner = PlatformRenderer.Navigation;
TargetApplication.NavigationProxy.Inner = _renderer.Navigation;
}
internal void DidAppear()
{
PlatformRenderer.Navigation.AnimateModalPages = false;
TargetApplication.NavigationProxy.Inner = PlatformRenderer.Navigation;
PlatformRenderer.Navigation.AnimateModalPages = true;
_renderer.Navigation.AnimateModalPages = false;
TargetApplication.NavigationProxy.Inner = _renderer.Navigation;
_renderer.Navigation.AnimateModalPages = true;
}
internal void WillAppear()
@ -259,10 +218,10 @@ namespace Xamarin.Forms.Platform.MacOS
var viewRenderer = CreateRenderer(view);
SetRenderer(view, viewRenderer);
PlatformRenderer.View.AddSubview(viewRenderer.NativeView);
_renderer.View.AddSubview(viewRenderer.NativeView);
if (viewRenderer.ViewController != null)
PlatformRenderer.AddChildViewController(viewRenderer.ViewController);
viewRenderer.SetElementSize(new Size(PlatformRenderer.View.Bounds.Width, PlatformRenderer.View.Bounds.Height));
_renderer.AddChildViewController(viewRenderer.ViewController);
viewRenderer.SetElementSize(new Size(_renderer.View.Bounds.Width, _renderer.View.Bounds.Height));
}
else
Console.Error.WriteLine("A Renderer was already found, potential view double add");
@ -271,7 +230,7 @@ namespace Xamarin.Forms.Platform.MacOS
void HandleChildRemoved(object sender, ElementEventArgs e)
{
var view = e.Element;
DisposeModelAndChildrenRenderers(view);
view.DisposeModalAndChildRenderers();
}
}
}

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

@ -38,13 +38,17 @@ namespace Xamarin.Forms.Platform.MacOS
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!_disposed)
{
_platformNavigation.Dispose();
_platformNavigation = null;
Platform = null;
}
_disposed = true;
}
base.Dispose(disposing);
}
}

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

@ -15,8 +15,9 @@ namespace Xamarin.Forms.Platform.MacOS
static int s_sectionCount;
readonly nfloat _defaultSectionHeight;
readonly Dictionary<DataTemplate, int> _templateToId = new Dictionary<DataTemplate, int>();
readonly NSTableView _nsTableView;
protected readonly ListView List;
NSTableView _nsTableView;
ListView List;
bool _disposed;
ITemplatedItemsView<Cell> TemplatedItemsView => List;
@ -185,6 +186,26 @@ namespace Xamarin.Forms.Platform.MacOS
return nativeCell;
}
protected override void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
if (List != null)
{
List.ItemSelected -= OnItemSelected;
List = null;
}
_nsTableView = null;
}
_disposed = true;
base.Dispose(disposing);
}
protected virtual Cell GetCellForPath(NSIndexPath indexPath, bool isGroupHeader)
{
var templatedItems = TemplatedItemsView.TemplatedItems;

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

@ -40,23 +40,13 @@ namespace Xamarin.Forms.Platform.MacOS
protected override void Dispose(bool disposing)
{
if (disposing && !_disposed)
{
_disposed = true;
if (_disposed)
return;
var viewsToLookAt = new Stack<NSView>(Subviews);
while (viewsToLookAt.Count > 0)
if (disposing)
{
var view = viewsToLookAt.Pop();
var viewCellRenderer = view as ViewCellNSView;
if (viewCellRenderer != null)
viewCellRenderer.Dispose();
else
{
foreach (var child in view.Subviews)
viewsToLookAt.Push(child);
}
}
foreach (NSView subview in Subviews)
DisposeSubviews(subview);
if (Element != null)
{
@ -64,21 +54,53 @@ namespace Xamarin.Forms.Platform.MacOS
templatedItems.CollectionChanged -= OnCollectionChanged;
templatedItems.GroupedCollectionChanged -= OnGroupedCollectionChanged;
}
if (_dataSource != null)
{
_dataSource.Dispose();
_dataSource = null;
}
if (disposing)
if (_headerRenderer != null)
{
ClearHeader();
_headerRenderer.Element?.DisposeModalAndChildRenderers();
_headerRenderer = null;
}
if (_footerRenderer != null)
{
Platform.DisposeModelAndChildrenRenderers(_footerRenderer.Element);
_footerRenderer.Element?.DisposeModalAndChildRenderers();
_footerRenderer = null;
}
}
_disposed = true;
base.Dispose(disposing);
}
void DisposeSubviews(NSView view)
{
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.
if (view is NSClipView)
return;
foreach (NSView subView in view.Subviews)
DisposeSubviews(subView);
view.RemoveFromSuperview();
}
view.Dispose();
}
protected override void SetBackgroundColor(Color color)
{
base.SetBackgroundColor(color);
@ -229,7 +251,7 @@ namespace Xamarin.Forms.Platform.MacOS
_table.HeaderView = null;
if (_headerRenderer == null)
return;
Platform.DisposeModelAndChildrenRenderers(_headerRenderer.Element);
_headerRenderer.Element.DisposeModalAndChildRenderers();
_headerRenderer = null;
}

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

@ -88,9 +88,21 @@ namespace Xamarin.Forms.Platform.MacOS
{
if (Element != null)
{
NavigationPage?.SendDisappearing();
if (NavigationPage != null)
{
NavigationPage.PushRequested -= OnPushRequested;
NavigationPage.PopRequested -= OnPopRequested;
NavigationPage.PopToRootRequested -= OnPopToRootRequested;
NavigationPage.RemovePageRequested -= OnRemovedPageRequested;
NavigationPage.InsertPageBeforeRequested -= OnInsertPageBeforeRequested;
NavigationPage.Popped -= OnPopped;
NavigationPage.PoppedToRoot -= OnPoppedToRoot;
NavigationPage.SendDisappearing();
}
((Element as IPageContainer<Page>)?.CurrentPage as Page)?.SendDisappearing();
Element.PropertyChanged -= OnElementPropertyChanged;
Platform.SetRenderer(Element, null);
Element = null;
}
@ -100,7 +112,19 @@ namespace Xamarin.Forms.Platform.MacOS
_events?.Dispose();
_events = null;
if(_currentStack != null)
{
foreach (var childPageWrapper in _currentStack)
{
childPageWrapper.Dispose();
}
_currentStack.Clear();
_currentStack = null;
}
Platform.NativeToolbarTracker.Navigation = null;
_disposed = true;
}
base.Dispose(disposing);
}
@ -175,22 +199,19 @@ namespace Xamarin.Forms.Platform.MacOS
{
ConfigurePageRenderer();
var navPage = (NavigationPage)Element;
if (navPage.CurrentPage == null)
if (NavigationPage.CurrentPage == null)
throw new InvalidOperationException(
"NavigationPage must have a root Page before being used. Either call PushAsync with a valid Page, or pass a Page to the constructor before usage.");
Platform.NativeToolbarTracker.Navigation = navPage;
Platform.NativeToolbarTracker.Navigation = NavigationPage;
NavigationPage.PushRequested += OnPushRequested;
NavigationPage.PopRequested += OnPopRequested;
NavigationPage.PopToRootRequested += OnPopToRootRequested;
NavigationPage.RemovePageRequested += OnRemovedPageRequested;
NavigationPage.InsertPageBeforeRequested += OnInsertPageBeforeRequested;
navPage.Popped += (sender, e) => Platform.NativeToolbarTracker.UpdateToolBar();
navPage.PoppedToRoot += (sender, e) => Platform.NativeToolbarTracker.UpdateToolBar();
NavigationPage.Popped += OnPopped;
NavigationPage.PoppedToRoot += OnPoppedToRoot;
UpdateBarBackgroundColor();
UpdateBarTextColor();
@ -199,7 +220,7 @@ namespace Xamarin.Forms.Platform.MacOS
_events.LoadEvents(NativeView);
_tracker = new VisualElementTracker(this);
navPage.Pages.ForEach(async p => await PushPageAsync(p, false));
NavigationPage.Pages.ForEach(async p => await PushPageAsync(p, false));
UpdateBackgroundColor();
}
@ -213,6 +234,16 @@ namespace Xamarin.Forms.Platform.MacOS
return pageRenderer;
}
void OnPopped(object sender, NavigationEventArgs e)
{
Platform.NativeToolbarTracker.UpdateToolBar();
}
void OnPoppedToRoot(object sender, NavigationEventArgs e)
{
Platform.NativeToolbarTracker.UpdateToolBar();
}
void InsertPageBefore(Page page, Page before)
{
if (before == null)
@ -229,17 +260,19 @@ namespace Xamarin.Forms.Platform.MacOS
var vc = CreateViewControllerForPage(page);
vc.SetElementSize(new Size(View.Bounds.Width, View.Bounds.Height));
page.Layout(new Rectangle(0, 0, View.Bounds.Width, View.Frame.Height));
vc.NativeView.WantsLayer = true;
var beforeViewController = Platform.GetRenderer(before).ViewController;
var beforeControllerIndex = ChildViewControllers.IndexOf(beforeViewController);
var beforeRenderer = Platform.GetRenderer(before);
var beforeControllerIndex = ChildViewControllers.IndexOf(beforeRenderer.ViewController);
InsertChildViewController(vc.ViewController, beforeControllerIndex);
View.AddSubview(vc.NativeView);
View.AddSubview(vc.NativeView, NSWindowOrderingMode.Below, beforeRenderer.NativeView);
}
void OnInsertPageBeforeRequested(object sender, NavigationRequestedEventArgs e)
{
InsertPageBefore(e.Page, e.BeforePage);
Platform.NativeToolbarTracker.UpdateNavigationItems(true);
}
void OnPopRequested(object sender, NavigationRequestedEventArgs e)
@ -325,11 +358,11 @@ namespace Xamarin.Forms.Platform.MacOS
if (animated)
{
var previousPageRenderer = Platform.GetRenderer(previousPage);
var previousPageRenderer = CreateViewControllerForPage(previousPage);
var transitionStyle = NavigationPage.OnThisPlatform().GetNavigationTransitionPopStyle();
return await this.HandleAsyncAnimation(target.ViewController, previousPageRenderer.ViewController,
ToViewControllerTransitionOptions(transitionStyle), () => Platform.DisposeRendererAndChildren(target), true);
ToViewControllerTransitionOptions(transitionStyle), () => target.DisposeRendererAndChildren(), true);
}
RemovePage(page, false);

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

@ -11,8 +11,9 @@ namespace Xamarin.Forms.Platform.MacOS
const string HeaderIdentifier = nameof(TextCell);
const string ItemIdentifier = nameof(ViewCell);
readonly NSTableView _nsTableView;
readonly TableView _tableView;
NSTableView _nsTableView;
TableView _tableView;
bool _disposed;
public TableViewDataSource(TableViewRenderer tableViewRenderer)
{
@ -39,7 +40,7 @@ namespace Xamarin.Forms.Platform.MacOS
var cell = _tableView.Model.GetCell(sectionIndex, itemIndexInSection);
_tableView.Model.RowSelected(cell);
if (AutomaticallyDeselect)
_nsTableView.DeselectRow(row);
_nsTableView?.DeselectRow(row);
}
public override nint GetRowCount(NSTableView tableView)
@ -91,6 +92,20 @@ namespace Xamarin.Forms.Platform.MacOS
return nativeCell;
}
protected override void Dispose(bool disposing)
{
if(disposing)
{
if(!_disposed)
{
_nsTableView = null;
_tableView = null;
_disposed = true;
}
}
base.Dispose(disposing);
}
void GetComputedIndexes(nint row, out int sectionIndex, out int itemIndexInSection, out bool isHeader)
{
var totalItems = 0;

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

@ -7,6 +7,7 @@ namespace Xamarin.Forms.Platform.MacOS
public class TableViewRenderer : ViewRenderer<TableView, NSView>
{
const int DefaultRowHeight = 44;
bool _disposed;
internal NSTableView TableView { get; set; }
@ -17,15 +18,19 @@ namespace Xamarin.Forms.Platform.MacOS
protected override void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
var viewsToLookAt = new Stack<NSView>(Subviews);
while (viewsToLookAt.Count > 0)
{
var view = viewsToLookAt.Pop();
var viewCellRenderer = view as IVisualElementRenderer;
var viewCellRenderer = view as ViewCellNSView;
if (viewCellRenderer != null)
{
viewCellRenderer.RemoveFromSuperview();
viewCellRenderer.Dispose();
}
else
@ -35,6 +40,7 @@ namespace Xamarin.Forms.Platform.MacOS
}
}
}
_disposed = true;
base.Dispose(disposing);
}

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

@ -237,10 +237,13 @@
<Link>VisualElementRenderer.cs</Link>
</Compile>
<Compile Include="Extensions\NSMenuExtensions.cs" />
<Compile Include="..\Xamarin.Forms.Platform.iOS\DisposeHelpers.cs">
<Link>DisposeHelpers.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Xamarin.Forms.Platform\Xamarin.Forms.Platform.csproj">
<Project>{67F9D3A8-F71E-4428-913F-C37AE82CDB24}</Project>
<Project>{D31A6537-ED9C-4EBD-B231-A8D4FE44126A}</Project>
<Name>Xamarin.Forms.Platform</Name>
</ProjectReference>
<ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">

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

@ -1,4 +1,9 @@
#if __MOBILE__
namespace Xamarin.Forms.Platform.iOS
#else
namespace Xamarin.Forms.Platform.MacOS
#endif
{
internal static class DisposeHelpers
{
@ -27,9 +32,11 @@ namespace Xamarin.Forms.Platform.iOS
{
if (renderer.ViewController != null)
{
#if __MOBILE__
var modalWrapper = renderer.ViewController.ParentViewController as ModalWrapper;
if (modalWrapper != null)
modalWrapper.Dispose();
#endif
}
renderer.NativeView.RemoveFromSuperview();
@ -47,14 +54,16 @@ namespace Xamarin.Forms.Platform.iOS
if (rendererToRemove.Element != null && Platform.GetRenderer(rendererToRemove.Element) == rendererToRemove)
rendererToRemove.Element.ClearValue(Platform.RendererProperty);
if (rendererToRemove.NativeView != null)
{
var subviews = rendererToRemove.NativeView.Subviews;
for (var i = 0; i < subviews.Length; i++)
{
if (subviews[i] is IVisualElementRenderer childRenderer)
DisposeRendererAndChildren(childRenderer);
}
rendererToRemove.NativeView.RemoveFromSuperview();
}
rendererToRemove.Dispose();
}
}

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

@ -107,9 +107,13 @@ namespace Xamarin.Forms.Platform.MacOS
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_elementPropertyChanged = null;
_controlChanging = null;
_controlChanged = null;
if (disposing && Control != null && ManageNativeControlLifetime)
if (Control != null && ManageNativeControlLifetime)
{
Control.RemoveFromSuperview();
Control.Dispose();
@ -117,6 +121,9 @@ namespace Xamarin.Forms.Platform.MacOS
}
}
base.Dispose(disposing);
}
protected override void OnElementChanged(ElementChangedEventArgs<TView> e)
{
base.OnElementChanged(e);