2 Stimmen

UITableViewController ist leer, nachdem er eine Speicherwarnung erhalten hat

Ich zeichne eine Tabellenansicht in MonoTouch, indem ich die Unterklasse UITableViewController y UITableViewSource (nicht UITableViewDataSource !!!). Im Konstruktor meines Viewcontrollers habe ich die Quelle der Tabellenansicht so eingestellt:

TableView.Source = new CustomTableViewSource();

Und in meinem CustomTableViewSource Ich konstruiere die Zelle der Tabellenansicht. Es funktioniert gut, außer wenn ich eine Speicherwarnung im iPhone-Simulator simuliere. Wenn die Ansicht ausgeblendet wird (z.B. ein anderer Viewcontroller in der Tab-Leiste ausgewählt ist), wenn ich zurückkomme, ist die Tabellenansicht einfach leer (weißer Hintergrund, keine Tabellenansicht mehr).

Ich tue jedoch nichts in der DidReceiveMemoryWarning Rückruf. Ich habe auch versucht, die TableViewSource en el viewWillAppear (wenn ich eine Speicherwarnung erhalten habe), aber kein Erfolg mehr...

Ist es ein Problem mit dem Garbage Collector? Ich weiß, dass GC.Collect wird aufgerufen, wenn eine Speicherwarnung eingeht. Vielleicht ist der Garbage Collector nur wegwerfen meine Ansicht und ich muss es vollständig wieder anzeigen?

2voto

Dimitris Tavlikos Punkte 8158

Sie sollten die Tabellenquelle in der Methode ViewDidLoad und nicht im Konstruktor initialisieren. Diese Methode wird aufgerufen, wenn ein View-Controller geladen wird und dann jedes Mal, wenn der View des Controllers nach einer Speicherwarnung neu erstellt werden muss.

Ich habe einige Tests durchgeführt und erhalte ähnliche Ergebnisse nach einer Speicherwarnung. Allerdings erhalte ich nur eine leere Tabellenansicht. Wenn ich die Tabellenquelle in der ViewWillAppear wieder einstelle, wird die Tabelle normal mit Daten gefüllt.

Die Tatsache, dass Ihre Implementierung in ViewWillAppear nicht funktioniert, lässt mich vermuten, dass die Methode nicht einmal aufgerufen wird. Wenn das der Fall ist, vermute ich, dass Ihre Tabellenansicht nicht neu erstellt wird, wenn sie benötigt wird.

Dies kann unter bestimmten Umständen passieren, wenn Sie Controller verwenden, deren Ansichten nicht aus einer XIB-Datei erstellt werden. In diesem Fall sollten Sie den View in der LoadView-Methode erstellen (ohne base.LoadView() aufzurufen):

public override void LoadView()
{
    this.View = new UITableView(UIScreen.MainScreen.ApplicationFrame); //or something similar
}

Ich hatte ähnliche Probleme (Tabellenansichten wurden nicht neu erstellt) mit einer komplexen Hierarchie von Registerkarten-Controllern, die Navigations-Controller enthielten, die View-Controller enthielten usw. Die Probleme wurden gelöst, als ich die LoadView-Methode zur Verfügung stellte.

Ich kann nicht mehr raten ;)

1voto

poupou Punkte 43207

Sie haben Recht, dass GC.Collect() wird aufgerufen, wenn eine Speicherwarnung eingeht. Dies ist eine ernstzunehmende Warnung des Betriebssystems und MonoTouch wird versuchen, seinen eigenen Speicher freizugeben (wenn möglich). Sie können dies erweitern, indem Sie die Funktion DidReceiveMemoryWarning So kann Ihre Anwendung auch Speicher freigeben, den sie nicht unbedingt benötigt.

Dieser Aufruf an den GC (wie jeder andere) bedeutet, dass jedes Objekt, auf das nicht verwiesen wird, eingesammelt und freigegeben werden kann. Jetzt kann Ihr CustomTableViewSource Instanz sollte nicht gesammelt werden (es sei denn, Ihr TableView ist). Im Zweifelsfall können Sie dies überprüfen, indem Sie einen Finalizer für den Typ hinzufügen, z. B.

~CustomTableViewSource ()
{
    Console.WriteLine ("~CustomTableViewSource");
}

Allerdings sind die Objekte, die Teil Ihrer CustomTableViewSource podría gesammelt werden (wenn nicht referenziert), wie es bei anderen Teilen (UI) Ihrer Tabelle der Fall sein könnte. Das ist unmöglich zu sagen, ohne den Quellcode zu sehen.

Ich schlage vor, dass Sie versuchen, herauszufinden, was freigegeben wird, und von dort aus sollten Sie sehen, was benötigt wird, um entweder eine Referenz zu behalten (um zu vermeiden, dass sie gesammelt werden) oder was neu erstellt werden muss (wenn einige Instanzen absichtlich freigegeben wurden).

1voto

nicolas Punkte 489

Zusammenfassend lässt sich sagen, dass meine Lösung funktioniert:

public class LoginViewController : UITableViewController
{
  LoginDataSource m_loginDataSource;

  public LoginViewController(UITableViewStyle withStyle) : base(withStyle)
  {
   m_loginDataSource = new LoginDataSource(this);
  }

  public override void LoadView()
  {
    this.View = new UITableView(UIScreen.MainScreen.ApplicationFrame,  UITableViewStyle.Grouped);
  }

  public override void ViewDidLoad ()
  {
    base.ViewDidLoad ();
    TableView.Source = m_loginDataSource;
  }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X