如何在c#Xamarin中实现ios委托/数据源模式?

时间:2013-08-31 10:27:32

标签: c# ios objective-c xamarin.ios xamarin

如何在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#中完成?并不是那么危险,因为来电者可能不知道它的弱引用?

3 个答案:

答案 0 :(得分:2)

我建议您使用Profiler来查看是否真的是内存泄漏。如果您发现它确实是一个问题,您可能会使用WeakReference class弱引用该委托,该{{3}}包含对象的弱引用。

答案 1 :(得分:0)

垃圾收集器非常能够处理循环引用。你不必担心它。

答案 2 :(得分: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收集对象时,它们实际上是从内存中释放的。

在您的情况下,我认为正在进行的是View保存对DataSource的引用,该DataSource包含对ViewController的引用。 ViewController不是GCed,因为View保存了对它的引用,即使没有引用指向此View,GC也不会收集它,因为该对象的引用数仍为2.实际上,本机中的ViewController具有仍然是对这种观点的参考。