2012-03-28 2 views
2

Je dessine une vue de table dans MonoTouch en sous-classes UITableViewController et UITableViewSource (pas UITableViewDataSource !!!). Dans le constructeur de mon contrôleur de vue, je mets la vue tableau source comme que:UITableViewController est vide après avoir reçu un avertissement de mémoire

TableView.Source = new CustomTableViewSource(); 

Et dans mon CustomTableViewSource, je suis la construction de la cellule de la vue du tableau. C'est super, sauf quand je simule un avertissement de mémoire dans le simulateur de l'iPhone. Si la vue est masquée (par exemple, un autre contrôleur de vue dans la barre d'onglets est sélectionné), lorsque je reviens, la vue de table est simplement vide (arrière-plan blanc, plus de vue de table).

Cependant, je ne fais rien dans le rappel DidReceiveMemoryWarning. J'ai également essayé de mettre de nouveau le TableViewSource dans le viewWillAppear (si reçu un avertissement de mémoire) mais pas plus de succès ...

Est-ce un problème de garbage collector? Je sais que GC.Collect est appelée lors de la réception d'avertissement de la mémoire. Peut-être que le garbage collector jette juste mon point de vue et que je dois l'afficher entièrement à nouveau?

+1

Publiez votre '' ViewDidLoad' et méthodes ViewDidUnload'. – jonathanpeppers

Répondre

2

Vous devez initialiser la source de table dans la méthode ViewDidLoad et non dans le constructeur. Cette méthode est appelée lorsqu'un contrôleur de vue est chargé et chaque fois que la vue du contrôleur doit être recréée après un avertissement de mémoire.

J'ai fait quelques tests et j'obtiens des résultats similaires après un avertissement de mémoire. Cependant, je reçois seulement une vue de table vide. Lorsque je définis à nouveau la source de la table dans le ViewWillAppear, la table est remplie avec des données normalement.

Le fait que votre implémentation dans le ViewWillAppear ne fonctionne pas, me fait penser que la méthode n'est même pas appelée. Si c'est le cas, je devine que votre vue de table n'est pas recréée quand elle doit le faire.

Cela peut se produire dans certaines circonstances lorsque vous utilisez des contrôleurs dont les vues ne sont pas créées à partir d'un fichier XIB. Dans ce cas, vous devez créer la vue dans la méthode LoadView (sans appeler la base.Loadview()):

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

j'ai eu des problèmes similaires (vues de table où pas recréés) avec une hiérarchie complexe de contrôleurs onglet contenant les contrôleurs de navigation, qui contenaient vue des contrôleurs, etc. Les problèmes ont été résolus lorsque je fournis la méthode LoadView.

Je suis sur des suppositions;)

+1

Merci beaucoup! C'est réglé mon problème! Désolé, j'aurais dû fournir plus d'informations. Comme vous l'avez deviné, je n'utilise pas un fichier XIB mais crée ma vue de table avec du code. 'LoadView()' n'a pas été implémenté. – nicolas

+0

De rien! –

1

Vous avez raison: GC.Collect() sera appelée lors de la réception d'un avertissement de mémoire. Ceci est un avertissement sérieux du système d'exploitation et MonoTouch essayera de libérer sa propre mémoire (si possible). Vous pouvez étendre cela en remplaçant DidReceiveMemoryWarning, afin que votre application puisse également libérer toute la mémoire dont elle n'a pas absolument besoin.

Cet appel au GC (comme tout autre) signifie que chaque objet qui n'est pas référencé peut être collecté et libéré. Maintenant votre instance CustomTableViewSource ne doit pas être collectée (sauf si votre TableView est). Dans le doute, vous pouvez vérifier cela en ajoutant un finaliseur pour le type, par exemple.

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

Cependant, les objets qui font partie de votre CustomTableViewSourcepourrait être collectées (si non référencé) que d'autres parties (UI) de votre table pourrait être. C'est impossible à dire sans voir le code source.

Je vous suggère d'essayer de savoir ce qui est libéré et à partir de là vous devriez voir ce qu'il faut pour garder une référence (pour éviter qu'ils soient collectés) ou ce qui doit être recréé (si certaines instances ont été libérées) .

1

Pour résumer, ma solution qui fonctionne est:

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

Pas besoin de complexe. Faites simplement TableView.Source = new LoginDataSource (this) dans la méthode ViewDidLoad. –

+0

Droite :-) Mise à jour :-) – nicolas

Questions connexes