如何在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 :(得分: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具有仍然是对这种观点的参考。