2016-12-19 148 views
1

在我的應用程序中,使用Xamarin Profiler,我注意到無論何時將VC推入堆棧並導航回內存分配都不是免費的。如果我再次推動相同的視圖,它會增加更多的內存。向後導航不會釋放內存

我創建了一個示例項目來測試,我發現這是做同樣的事情。

示例項目:

我有兩個視圖控制器,VC1和VC2。 VC1是根視圖控制器。

每當我從VC1推VC2時,都會分配內存,但是當我導航回時,內存不是免費的。如果我繼續推VC2,它會增加更多內存。在VC2中,我通過設計師添加了3個標籤。

中的AppDelegate:

namespace TestSample 
{ 
    [Register("AppDelegate")] 
    public class AppDelegate : UIApplicationDelegate 
    { 
     public override UIWindow Window 
     { 
      get; 
      set; 
     } 

     public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) 
     { 
      Window = new UIWindow(UIScreen.MainScreen.Bounds); 
      var nav = new UINavigationController(new MyViewController()); 
      Window.RootViewController = nav; 
      Window.MakeKeyAndVisible(); 

      return true; 
     } 
    } 
} 

VC1:

namespace TestSample 
{ 
    public partial class MyViewController : UIViewController 
    { 
     public MyViewController() : base("MyViewController", null) 
     { 
     } 

     public override void ViewDidLoad() 
     { 
      base.ViewDidLoad(); 
      // Perform any additional setup after loading the view, typically from a nib. 
     } 
     public override void ViewWillAppear(bool animated) 
     { 
      base.ViewWillAppear(animated); 

      btn1.TouchUpInside += Btn1_TouchUpInside; 
     } 

     void Btn1_TouchUpInside(object sender, EventArgs e) 
     { 
      NavigationController.PushViewController(new MyViewController2(), true); 
     } 

     public override void ViewDidDisappear(bool animated) 
     { 
      base.ViewDidDisappear(animated); 
      btn1.TouchUpInside -= Btn1_TouchUpInside; 
     } 

     public override void DidReceiveMemoryWarning() 
     { 
      base.DidReceiveMemoryWarning(); 
      // Release any cached data, images, etc that aren't in use. 
     } 
    } 
} 

VC2:在Xamarin.iOS

namespace TestSample 
{ 
    public partial class MyViewController2 : UIViewController 
    { 
     public MyViewController2() : base("MyViewController2", null) 
     { 
     } 

     public override void ViewDidLoad() 
     { 
      base.ViewDidLoad(); 
      // Perform any additional setup after loading the view, typically from a nib. 
     } 

     public override void DidReceiveMemoryWarning() 
     { 
      base.DidReceiveMemoryWarning(); 
      // Release any cached data, images, etc that aren't in use. 
     } 

     public override void ViewDidDisappear(bool animated) 
     { 
      base.ViewDidDisappear(animated); 
      /*foreach (UIView view in View.Subviews) { 
       view.RemoveFromSuperview(); 
      }*/ 

      label1.RemoveFromSuperview(); 
      label2.RemoveFromSuperview(); 
      label3.RemoveFromSuperview(); 

      label1.Dispose(); 
      label2.Dispose(); 
      label3.Dispose(); 
     } 
    } 
} 
+0

你可以發佈你的VC2嗎?這裏有一個循環引用,需要通過設置null或調用Dispose()來切斷關係,否則GC將永遠看不到有資格收集的對象。 –

+0

VC2只有3個標籤,我通過設計者在XIB文件中添加了這些標籤。編輯VC2 – PLOW

+0

@PLOW如果強制使用'GC.Collect()',回收內存? – SushiHangover

回答

5

垃圾收集完全不破。這是一種普遍的誤解(在任何系統上),擁有GC意味着不必擔心注意內存消耗和(強)參考。

X.iOS位於參考計數世界之上,這需要進行特定的測量。所有這些都被記錄在案;是的,它可能很難理解所有的細微差別。

這就是說:我試過你的例子,VC2按預期方式收集(終結者和Dispose()被稱爲)。 Profiler(1.0.2-2)也不顯示任何泄漏。

我創建了兩個基於XIB的控制器,並向第一個和第三個標籤添加了一個按鈕。您不必刪除或處理任何標籤,也不必在案例中的第一個VC中取消訂閱點擊事件。

如果你的項目行爲不同,你會在某處保留對VC2的引用。也許你可以提供完整的項目,然後我可以看看它。