Reputation: 20279
Consider this simple example:
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;
}
}
I've noticed that the view controller (TableViewController) is never released. The table view controller has a reference to the data source, but the data source also has a reference to the table view controller.
With TableView.Source = new TableSource();
the view controller gets released, with TableView.Source = new TableSource(this);
it's not.
How should this reference cycle be broken so that everything get released?
Edit:
Now I tried the WeakReference
:
Through using a WeakReference
the Dispose
method is called, when the view controller is popped off the navigation stack.
In ViewDidLoad
:
TableView.Source = new TableSource(new WeakReference<TableViewController> (this));
In the datasource:
private WeakReference<TableViewController> controller;
public TableSource (WeakReference<TableViewController> controller)
{
this.controller = controller;
}
I built this into my real project, but how can I access my controller? I get the message
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?
Upvotes: 2
Views: 597
Reputation: 5234
You can move the methods into the controller itself which would be less of a hassle than WeakReference. Then mark them with export attribute which then allows you to set the UITableView.WeakDataSource property to the controller itself.
[Export("tableView:numberOfRowsInSection:")]
public nint RowsInSection (UITableView tableview, nint section)
[Export("tableView:cellForRowAtIndexPath:")]
public UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
Once they are moved you can attach the datasource:
public override void ViewDidLoad ()
{
TableView.WeakDataSource = this;
}
Upvotes: -1
Reputation: 3362
change
public partial class TableViewController : UITableViewController
to
public partial class TableViewController : UITableViewController, UITableViewSource
and in ViewDidLoad just do
self.TableView.Source = self;
the source property is a weak reference internally already so your have no problem of managing that. It is a convenience property to make the tbaleviewcontroller the delegate and datasource altogether. (Just like you would in native iOS)
Upvotes: -1
Reputation: 1557
You work with Xamarin, as I see? Have you tried WeakReference? https://msdn.microsoft.com/en-us/library/system.weakreference(v=vs.110).aspx
PS:
private WeakReference weakController;
to set:
this.weakController = new WeakReference(controller);
to get:
if (weakController.isAlive)
{
TableViewController controller = weakController.Target as TableViewController;
}
Upvotes: 4