2013-08-31 55 views
3

如何在c#Xamarin中實現iOS用於表視圖的「委託」或「數據源」模式的等價物?例如,我想有視圖類,如:如何在c#Xamarin中實現ios委託/數據源模式?

public class MyDataView : UIView 
{ 
    public interface ISource 
    { 
    int NumberOfPages(); 
    } 

    public ISource DataSource { get; set; } 
} 

但問題是,當我把這個從MyViewController下面類似的代碼:

this.myDataView.DataSource=new ViewSource(this) 

public class ViewSource : MyDataView.ISource 
{ 
    private readonly MyViewController parentController; 

    public ViewSource(MyViewController parentController) 
    { 
    this.parentController=parentController; 
    } 
} 

然後MyViewController永遠不能被垃圾收集,因爲創建了循環參考。

這似乎是一個常見的要求,所以人們使用什麼設計?

我應該讓Source成爲一個弱引用嗎?這是如何在C#中完成的?因爲呼叫者可能不知道它是一個弱引用,所以這不危險嗎?

+0

你的解決方案是什麼? – testing

回答

0

垃圾收集器相當有能力處理循環引用。你不必擔心它。

+1

那麼,這可能是理論,但在上面的例子中,如果我將它傳遞給ViewSource構造函數(即,我的重寫Dispose從不調用),MyViewController對象從不會被釋放,而如果我傳遞null,它就會正常釋放。有任何想法嗎? – Bbx

0

我個人在MonoTouch上經常遇到拋棄內存的問題。我現在所做的是,我調用Dispose()並將目標c層中存在的每個對象都設置爲null。

public class AView : UIView { 

    private UIView tip; 
    private UIView top; 

    protected override void Dispose(bool disposing) { 
     base.Dispose(disposing); 
     this.ReleaseDesignerOutlets(); 

     if (this.tip != null) { 
      this.tip.Dispose(); 
      this.tip = null; 
     } 

     if (this.top != null) { 
      this.top.Dispose(); 
      this.top = null; 
     } 
    } 

} 

我不認爲「dealloc的」綁定到Dispose()方法,當管理對象被通過在託管環境中的GC收集這個人是隻叫。這並不意味着本地對象會死掉,它只是意味着在託管環境中沒有任何參考。當本地對象要在託管環境中顯示時,Mono運行時將創建(或重新使用已創建的對象)與本地對象綁定並增加後者的引用計數器的託管對象。 GC收集管理對象時,會減少參考計數器。如果Dispose()方法永遠不會被調用,這意味着GC沒有收集對象,因此該對象仍然有一個至少爲1的ref計數器。

我現在要說的是與我剛纔所說的有點矛盾。我認爲Mono Runtime不允許GCed對象再次出現在C#World中(我們不想讓神祕的新C#對象處於空狀態嗎?)。因此,即使對象在託管環境中沒有對它的引用,它們實際上也不會垃圾收集對象,直到ref計數器恰好爲1。因此,當GC收集對象時,它們實際上是從內存中釋放的。

你的情況是什麼(我認爲)是視圖持有對DataSource的引用,該DataSource持有對ViewController的引用。 ViewController沒有被GCed,因爲View持有對它的引用,即使沒有引用指向這個View,GC也不會收集它,因爲對象仍然有ref計數2.實際上,本地世界中的ViewController有仍然是對這個觀點的參考。

2

我建議你使用Profiler來查看是否真的是內存泄漏。如果您發現這確實是一個問題,那麼您可能會使用WeakReference class來弱引用委託,該委託包含對對象的弱引用。