Come interrompere il ciclo di riferimento tra controller di visualizzazione e origine dati

Considera questo semplice esempio:

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; } } 

Ho notato che il controller di visualizzazione (TableViewController) non viene mai rilasciato. Il controller della vista tabella ha un riferimento all’origine dati, ma l’origine dati ha anche un riferimento al controller vista tabella.

Con TableView.Source = new TableSource(); il controller della vista viene rilasciato, con TableView.Source = new TableSource(this); non è.

Come dovrebbe essere rotto questo ciclo di riferimento in modo che tutto venga rilasciato?

Modificare:

Ora ho provato il WeakReference :

Attraverso l’utilizzo di un WeakReference viene chiamato il metodo Dispose , quando il controller di visualizzazione viene estratto dallo stack di navigazione.

In ViewDidLoad :

 TableView.Source = new TableSource(new WeakReference (this)); 

Nell’origine dati:

 private WeakReference controller; public TableSource (WeakReference controller) { this.controller = controller; } 

L’ho costruito nel mio vero progetto, ma come posso accedere al mio controller ? Ricevo il messaggio

Digitare ‘System.WeakReference’ non contiene una definizione per ‘xxx’ e non è ansible trovare il metodo di estensione ‘xxx’ di tipo ‘System.WeakReference’. Ti manca un riferimento all’assemblaggio?

Lavori con Xamarin, come vedo? Hai provato WeakReference? https://msdn.microsoft.com/en-us/library/system.weakreference(v=vs.110).aspx

PS:

 private WeakReference weakController; 

impostare:

 this.weakController = new WeakReference(controller); 

ottenere:

 if (weakController.isAlive) { TableViewController controller = weakController.Target as TableViewController; } 

modificare

 public partial class TableViewController : UITableViewController 

a

 public partial class TableViewController : UITableViewController, UITableViewSource 

e in ViewDidLoad basta

 self.TableView.Source = self; 

la proprietà sorgente è già internamente un riferimento debole, quindi non hai problemi a gestirlo. È una proprietà di convenienza rendere il controllore tbaleview delegato e datasource del tutto. (Proprio come faresti in iOS nativo)

È ansible spostare i metodi nel controller stesso, il che sarebbe meno problematico di WeakReference. Quindi contrassegnali con l’attributo export che consente quindi di impostare la proprietà UITableView.WeakDataSource sul controller stesso.

 [Export("tableView:numberOfRowsInSection:")] public nint RowsInSection (UITableView tableview, nint section) [Export("tableView:cellForRowAtIndexPath:")] public UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath) 

Una volta spostati, è ansible albind l’origine dati:

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