如何打破视图控制器和数据源之间的引用循环
How to break reference cycle between view controller and data source
考虑这个简单的例子:
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) 从未发布过。 table 视图控制器引用了数据源,但数据源也引用了 table 视图控制器。
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;
}
我将其构建到我的真实项目中,但如何访问我的 控制器?我收到消息
Type 'System.WeakReference' does not contain a definition for 'xxx' and no extension method 'xxx' of type 'System.WeakReference' could be found. Are you missing an assembly reference?
如我所见,您使用的是 Xamarin?你试过弱引用吗?
https://msdn.microsoft.com/en-us/library/system.weakreference(v=vs.110).aspx
PS:
private WeakReference weakController;
设置:
this.weakController = new WeakReference(controller);
获得:
if (weakController.isAlive)
{
TableViewController controller = weakController.Target as TableViewController;
}
改变
public partial class TableViewController : UITableViewController
至
public partial class TableViewController : UITableViewController, UITableViewSource
然后在 ViewDidLoad 中执行
self.TableView.Source = self;
来源 属性 内部已经是弱引用,因此您可以轻松管理它。将 tbaleviewcontroller 一起作为委托和数据源很方便 属性。 (就像你在本地 iOS)
您可以将方法移动到控制器本身,这比 WeakReference 更省事。然后用导出属性标记它们,然后允许您将 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;
}
考虑这个简单的例子:
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) 从未发布过。 table 视图控制器引用了数据源,但数据源也引用了 table 视图控制器。
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;
}
我将其构建到我的真实项目中,但如何访问我的 控制器?我收到消息
Type 'System.WeakReference' does not contain a definition for 'xxx' and no extension method 'xxx' of type 'System.WeakReference' could be found. Are you missing an assembly reference?
如我所见,您使用的是 Xamarin?你试过弱引用吗? https://msdn.microsoft.com/en-us/library/system.weakreference(v=vs.110).aspx
PS:
private WeakReference weakController;
设置:
this.weakController = new WeakReference(controller);
获得:
if (weakController.isAlive)
{
TableViewController controller = weakController.Target as TableViewController;
}
改变
public partial class TableViewController : UITableViewController
至
public partial class TableViewController : UITableViewController, UITableViewSource
然后在 ViewDidLoad 中执行
self.TableView.Source = self;
来源 属性 内部已经是弱引用,因此您可以轻松管理它。将 tbaleviewcontroller 一起作为委托和数据源很方便 属性。 (就像你在本地 iOS)
您可以将方法移动到控制器本身,这比 WeakReference 更省事。然后用导出属性标记它们,然后允许您将 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;
}