UITableView qui ne se redessine pas... tant qu'on ne scroll pas

AliGatorAliGator Membre, Modérateur
juin 2009 modifié dans API UIKit #1
Bonjour les gens,

J'ai un petit souci avec une UITableView (c'est pas la première fois que ça m'arrive j'ai déjà  eu sur d'autres projets mais j'avais pas creusé plus loin) : elle refuse de se rafraà®chir même alors que ses données ont changé (et que je fais un reloadData)... je peux toujours attendre le nouveau contenu ne s'affiche pas c'est l'ancien qui reste... jusqu'à  ce que je fasse une action sur la TableView genre typiquement un scroll où là  enfin mes nouveaux éléments apparaissent...


En fait j'a une UITableView dont le dataSource puise ses données dans un NSMutableArray (jusque là  rien de très original), et j'ajoute ou supprime des éléments de ce NSMutableArray par programmation (sur réception d'un événement dans mon code qui me signale la présence d'un nouveau truc que je veux lister ou sa disparition). Sauf que j'ai beau faire ça :
-(void)addLine:(NSString*)str {<br />  [monTableau addObject:str];<br />  [maTableView reloadData];<br />  [maTableView setNeedsDisplay]; // (1) j&#39;ai mis ça mais ça change rien<br />  [maTableView layoutSubviews]; // (2) ça non plus ne rafraà®chit pas<br />}
bah quand j'appelle ma méthode addLine :
  • Mon tableau est bien modifié avec le nouvel objet (testé en faisant un NSLog dessus)
  • Le reloadData provoque un appel à  [tt]tableView: numberOfRowsInSection:[/tt] (mais pas à  [tt]cellForRowAtIndexPath:[/tt] même si le nombre de rows retourné est différent du précédent)
  • Le setNeedsDisplay ne change rien du tout
  • Le layoutSubviews provoque l'appel de cellForRowAtIndexPath: qui est finalement bien appelé autant de fois que j'ai de nouvelles lignes (je m'attendais à  ce que le reloadData l'appelle tout seul en plus du numberOfRowsInSection pourtant ?)
Mais malgré tout ça, à  l'écran (sur Simulateur comme sur Device !) la TableView ne se rafraà®chit pas (c'est toujours l'ancien contenu qui est visible)... et c'est seulement si je fais faire rien qu'un petit scroll sur la TableView que là  enfin le nouveau contenu apparaà®t à  l'écran !! Sinon je peux toujours attendre !


Vraiment là  je sèche, je vois pas pourquoi ma TV se rafraà®chit pas... J'ai même créé un UITableViewController en lui mettant ma tableView (qui ne prend pas tout l'écran pour mon cas) comme "view" (car avant je gérais le UITableViewDataSource avec mon propre contrôleur) me disant que la UITableViewController faisait peut-être des trucs en plus... que dalle même problème.

Ce que je comprends d'autant moins c'est que sur des exemples Apple comme BonjourWeb qui a un peu le même principe que mon app (une UITableView qui est remplie par code sans interventions de l'utilisateur par une UI) quand un nouveau service web est détecté le refresh se fait bien... Et je ne vois pas côté code ce que j'ai de différent par rapport à  leur code, où ils se contentent de faire un reloadData...


Donc là  je vois pas.... toutes les idées sont les bienvenues...

Réponses

  • allianallian Membre
    16:54 modifié #2
    Je vois pas trop pourquoi cela ne se rafraichit pas. Avant j'avais une TV que je peuplé grâce à  une BD et si j'ajoutais un élément par un clic sur un bouton par exemple rien qu'en faisant un reloadData cela se mettait à  jour.

    J'ai modifié mon appli du coup j'ai plus le code mais d'après mes souvenirs cela marchait bien.
  • AliGatorAliGator Membre, Modérateur
    juin 2009 modifié #3
    Alleluia, après avoir trimé déjà  un peu hier mais surtout toute la journée today, j'ai fini par trouver... c'est un peu alambiqué enfin j'aurais jamais pensé à  ça mais j'ai fini par trouver en testant un truc qui m'a fait tiquer... ouf !

    En fait pour résumer c'est parce que j'ajoutais mes éléments, et faisait un reloadData... à  partir d'un autre Thread, ce que je n'avais pas réalisé à  la base.

    C'est en essayant de faire un "performSelector:withObject:afterDelay:" (pS:wO:aD: pour les intimes), pour tenter de forcer le refresh de ma tableView un peu après (on sait jamais, vu que j'étais en train de tester un peu tout et n'importe quoi :P) que j'ai en effet réalisé que ce dernier n'était pas exécuté. Alors que quand j'appuyais sur un bouton dans mon interface graphique (pour vider ma tableView) ça se rafraichissait bien et le pS:wO:aD: était exécuté.

    J'ai cherché à  comprendre pourquoi, en lisant la doc j'ai réalisé que ce pS:wO:aD: installait un NSTimer sur la runloop... j'ai donc fait un [tt]CFRunLoopCopyMode(CFRunLoopGetCurrent())[/tt] qui m'a renvoyé nil... forcément si y'a pas de runloop qui s'exécute, je peux toujours attendre que mon timer se déclenche... et c'est là  que j'ai tilté que j'étais pas sur la RunLoop de mon mainThread... eh ouais, capilotracté mais qu'est ce que ça me soulage d'avoir trouvé !!



    En fait c'est mon thread secondaire qui vérifie régulièrement s'il y a des nouvelles infos ou pas qui appelle une methode de delegate perso pour me signaler quand j'ai de nouvelles infos. Donc la solution, ça a été de mémoriser le thread appelant quand je lance mon thread secondaire (via une méthode startWatchingUpdates), et de faire un performSelector:onThread:withObject:waitUntilDone: pour faire exécuter ma méthode de delegate "didReceiveUpdate" sur le thread appelant et non plus sur le thread secondaire.


    Comment ça vous n'avez rien compris ?
Connectez-vous ou Inscrivez-vous pour répondre.