2014-03-27 41 views
1

我已經使用Xamarin一段時間了,而且我遇到了一個很奇怪的問題。Xamarin內存回收問題

我可以崩潰一個非常簡單的兩個屏幕的應用程序。在第一個屏幕上,我有UIButtonTouchUpInside事件。第二,我有一個UIImageView與附加的圖像(從本地文件)。

所有我需要做的就是回遷和這兩個視圖 - 控制器之間的轉發,所有的時間。

當我連接Xcode的工具與活動監視器上,我發現我的簡單的應用程序達到〜100MB的內存內存被回收之前,那麼它的使用降到〜15MB。

但是,當我循環導航足夠長的時間,內存達到了140MB和應用程序崩潰。我在處理更復雜的應用程序時發現了這種行爲。當然,我採取一切可用的預防措施:

  • 上ViewWillDisappear退訂事件
  • 歸零代表等。

基本上,在我的應用程序複雜,我已經重寫了Dispose方法在我的基類所有UIViewControllers,我可以看到Dispose方法被調用disposing == false這是顯示每個視圖控制器。但是,內存使用量不會下降。

它有什麼問題?

我想指出的幾件事情:

  • 我Xamarin Studio是最新的,
  • 出現崩潰,而我是在iPhone 3GS的iOS 6.1.3
  • 測試在調試模式下的應用在簡單的應用程序中,圖像是一個1024x1024 JPG文件。

。由此一些代碼示例:

public partial class SimpleTestViewController : UIViewController 
{ 
    private UIButton button; 
    public SimpleTestViewController() : base ("SimpleTestViewController", null) { } 

    public override void DidReceiveMemoryWarning() 
    { 
     // Releases the view if it doesn't have a superview. 
     base.DidReceiveMemoryWarning(); 

     // Release any cached data, images, etc that aren't in use. 
    } 

    public override void ViewDidLoad() 
    { 
     base.ViewDidLoad(); 
     button = new UIButton (new RectangleF(0, 100, 100, 50)); 
     button.BackgroundColor = UIColor.Red; 
     button.TouchUpInside += (sender, e) => { 
      this.NavigationController.PushViewController(new SecondView(), true); 
     }; 
     this.Add (button); 

     // Perform any additional setup after loading the view, typically from a nib. 
    } 
} 

public partial class SecondView : UIViewController 
{ 
    private UIImageView _imageView; 

    public SecondView() : base ("SecondView", null) { } 

    public override void DidReceiveMemoryWarning() 
    { 
     // Releases the view if it doesn't have a superview. 
     base.DidReceiveMemoryWarning(); 

     // Release any cached data, images, etc that aren't in use. 
    } 

    public override void ViewDidLoad() 
    { 
     base.ViewDidLoad(); 

     _imageView = new UIImageView (new RectangleF(0,0, 200, 200)); 
     _imageView.Image = UIImage.FromFile ("Images/image.jpg"); 
     this.Add (_imageView); 
     // Perform any additional setup after loading the view, typically from a nib. 
    } 

    protected override void Dispose (bool disposing) 
    { 
     System.Diagnostics.Debug.WriteLine("Disposing " +this.GetType() 
      + " hash code " + this.GetHashCode() 
      + " disposing flag "+disposing); 
     base.Dispose (disposing); 
    } 
} 

回答

3

要創建的按鈕/圖像的一個實例,並將其存儲在支持字段,而你不是在你的控制器Dispose呼籲他們Dispose 。 Controller實例化它們,所以你必須清除它們。

在上面的例子中,你也解除wire不按鈕TouchUpInside事件。我建議不要爲此使用lambda表達式,並且實際上爲它創建一個方法使得以後更容易分離。

TouchUpInside -= this.Method; 

此外,您並未從您添加到的視圖中移除圖像。

我知道你說你的觀點做這些事情,它會dissapear,但是這不是在你的示例代碼發生。你能提供一個完整的工作例子,這些基本的照顧?

+0

+1事實上,爲了釋放資源是非常必要的,特別是在移動設備等受限制的設備中。 –

+0

OK,但我C#中Dispose模式是這樣的: 公衆覆蓋的Dispose(BOOL處置){ 如果 (處置) { _itemToDispose.Dispose(); } 當對象正在終結時,重寫方法Dispose將調用處置等於false,不是嗎?所以Dispose不會被_itemToDispose調用。 – Smr

+0

這就是爲什麼你必須將_itemToDipose設置爲null之後的if塊作爲額外的預防措施之後 –