如何打破视图控制器和数据源之间的引用循环

时间:2015-08-21 12:48:46

标签: c# ios memory-management xamarin xamarin.ios

考虑这个简单的例子:

public partial class TableViewController : UITableViewController
{
    public TableViewController (IntPtr handle) : base (handle)
    {
    }

    protected override void Dispose (bool disposing)
    {
        Console.WriteLine (String.Format ("{0} controller disposed - {1}", this.GetType (), this.GetHashCode ()));

        base.Dispose (disposing);
    }

    public override void ViewDidLoad ()
    {
        //TableView.Source = new TableSource(this);
        TableView.Source = new TableSource();
    }
}

public class TableSource : UITableViewSource {

    private TableViewController controller;
    string CellIdentifier = "TableCell";

    public TableSource ()
    {

    }

    public TableSource (TableViewController controller)
    {
        this.controller = controller;
    }

    public override nint RowsInSection (UITableView tableview, nint section)
    {
        return 1;
    }

    public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
    {
        UITableViewCell cell = tableView.DequeueReusableCell (CellIdentifier);

        //if there are no cells to reuse, create a new one
        if (cell == null){
            cell = new UITableViewCell (UITableViewCellStyle.Default, CellIdentifier);
        }

        cell.TextLabel.Text = "test";

        return cell;
    }
}

我注意到视图控制器(TableViewController)从未发布过。表视图控制器具有对数据源的引用,但数据源也具有对表视图控制器的引用。

使用TableView.Source = new TableSource();视图控制器将被释放,而TableView.Source = new TableSource(this);则不会。

如何破坏此参考周期以便一切都被释放?

修改

现在我尝试了WeakReference

通过使用WeakReference调用Dispose方法,当视图控制器弹出导航堆栈时。

ViewDidLoad

TableView.Source = new TableSource(new WeakReference<TableViewController> (this));

在数据源中:

private WeakReference<TableViewController> controller;

public TableSource (WeakReference<TableViewController> controller)
{
    this.controller = controller;
}

我将其构建到我的真实项目中,但是如何访问我的控制器?我收到了消息

  

类型'System.WeakReference'不包含'xxx'的定义,也没有找到'System.WeakReference'类型的扩展方法'xxx'。你错过了装配参考吗?

3 个答案:

答案 0 :(得分:3)

我看到你和Xamarin一起工作?你试过WeakReference吗? https://msdn.microsoft.com/en-us/library/system.weakreference(v=vs.110).aspx

PS:

targetObj = {
    customerId: "123",
    customerName: "John",
    orders: [
        "item1", "item2", "item3", "item4"
    ]       
}

设置:

private WeakReference weakController; 

得到:

this.weakController = new WeakReference(controller); 

答案 1 :(得分:-1)

变化

public partial class TableViewController : UITableViewController

public partial class TableViewController : UITableViewController, UITableViewSource

并在ViewDidLoad中执行

self.TableView.Source = self;

源属性在内部已经是一个弱引用,所以你没有管理它的问题。这是一个方便的属性,使tbaleviewcontroller成为委托和数据源。 (就像在原生iOS中一样)

答案 2 :(得分:-1)

您可以将方法移动到控制器本身,这比WeakReference更麻烦。然后使用export属性标记它们,然后允许您将UITableView.WeakDataSource属性设置为控制器本身。

[Export("tableView:numberOfRowsInSection:")]
public nint RowsInSection (UITableView tableview, nint section)

[Export("tableView:cellForRowAtIndexPath:")]
public UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)

移动后,您可以附加数据源:

public override void ViewDidLoad ()
{
    TableView.WeakDataSource = this;
}