From 50ac8e06da7ca2fc44dc33a4dbc96d24a597f037 Mon Sep 17 00:00:00 2001 From: "E.Z. Hart" Date: Wed, 12 Oct 2016 04:46:18 -0600 Subject: Fix MasterDetailPage/NavigationPage leaks on iPad (#426) * Remove Master page property changed handler to eliminate leak * Fix memory leaks with MasterDetailPage and NavigationPage on iOS --- .../Bugzilla44166.cs | 10 +-- .../Renderers/NavigationRenderer.cs | 8 ++- .../Renderers/TabletMasterDetailRenderer.cs | 79 ++++++++++++---------- 3 files changed, 57 insertions(+), 40 deletions(-) diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla44166.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla44166.cs index 4006faa4..40264f07 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla44166.cs +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla44166.cs @@ -61,7 +61,7 @@ namespace Xamarin.Forms.Controls }; } - #if UITEST +#if UITEST [Test] public void Bugzilla44166Test() { @@ -71,7 +71,7 @@ namespace Xamarin.Forms.Controls RunningApp.WaitForElement(q => q.Marked("Back")); RunningApp.Tap(q => q.Marked("Back")); - for(int n = 0; n < 10; n++) + for (var n = 0; n < 10; n++) { RunningApp.WaitForElement(q => q.Marked("GC")); RunningApp.Tap(q => q.Marked("GC")); @@ -82,7 +82,7 @@ namespace Xamarin.Forms.Controls } } - var pageStats = string.Empty; + string pageStats = string.Empty; if (_44166MDP.Counter > 0) { @@ -106,7 +106,7 @@ namespace Xamarin.Forms.Controls Assert.Fail($"At least one of the pages was not collected: {pageStats}"); } - #endif +#endif } [Preserve(AllMembers = true)] @@ -121,7 +121,7 @@ namespace Xamarin.Forms.Controls Master = new _44166Master(); Detail = new _44166Detail(); - } + } ~_44166MDP() { diff --git a/Xamarin.Forms.Platform.iOS/Renderers/NavigationRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/NavigationRenderer.cs index 654fc8ed..fdbd116d 100644 --- a/Xamarin.Forms.Platform.iOS/Renderers/NavigationRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/Renderers/NavigationRenderer.cs @@ -831,7 +831,13 @@ namespace Xamarin.Forms.Platform.iOS if (disposing) { ((IPageController)Child).SendDisappearing(); - Child = null; + + if (Child != null) + { + Child.PropertyChanged -= HandleChildPropertyChanged; + Child = null; + } + _tracker.Target = null; _tracker.CollectionChanged -= TrackerOnCollectionChanged; _tracker = null; diff --git a/Xamarin.Forms.Platform.iOS/Renderers/TabletMasterDetailRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/TabletMasterDetailRenderer.cs index 7b54faf6..a3fbd2ab 100644 --- a/Xamarin.Forms.Platform.iOS/Renderers/TabletMasterDetailRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/Renderers/TabletMasterDetailRenderer.cs @@ -57,10 +57,7 @@ namespace Xamarin.Forms.Platform.iOS IPageController PageController => Element as IPageController; IElementController ElementController => Element as IElementController; - protected MasterDetailPage MasterDetailPage - { - get { return _masterDetailPage ?? (_masterDetailPage = (MasterDetailPage)Element); } - } + protected MasterDetailPage MasterDetailPage => _masterDetailPage ?? (_masterDetailPage = (MasterDetailPage)Element); IMasterDetailPageController MasterDetailPageController => MasterDetailPage as IMasterDetailPageController; @@ -71,36 +68,50 @@ namespace Xamarin.Forms.Platform.iOS protected override void Dispose(bool disposing) { - if (!_disposed && disposing) - { - if (Element != null) - { - PageController.SendDisappearing(); - Element.PropertyChanged -= HandlePropertyChanged; - Element = null; - } - - if (_tracker != null) - { - _tracker.Dispose(); - _tracker = null; - } - - if (_events != null) - { - _events.Dispose(); - _events = null; - } - - if (_masterController != null) - { - _masterController.WillAppear -= MasterControllerWillAppear; - _masterController.WillDisappear -= MasterControllerWillDisappear; - } - - _disposed = true; - } - base.Dispose(disposing); + if (_disposed) + { + return; + } + + _disposed = true; + + if (disposing) + { + if (Element != null) + { + PageController.SendDisappearing(); + Element.PropertyChanged -= HandlePropertyChanged; + + if (MasterDetailPage?.Master != null) + { + MasterDetailPage.Master.PropertyChanged -= HandleMasterPropertyChanged; + } + + Element = null; + } + + if (_tracker != null) + { + _tracker.Dispose(); + _tracker = null; + } + + if (_events != null) + { + _events.Dispose(); + _events = null; + } + + if (_masterController != null) + { + _masterController.WillAppear -= MasterControllerWillAppear; + _masterController.WillDisappear -= MasterControllerWillDisappear; + } + + ClearControllers(); + } + + base.Dispose(disposing); } public VisualElement Element { get; private set; } -- cgit v1.2.3