Bug avec TableView/OutlineView
Hello,
Un p'tit problème que je n'arrive pas à m'expliquer...
Quand je recharge un tableau de cette façon:
[_tableView reloadData];
J'obtiens toujours ce bug de seconde position à l'envers:
Par contre, si j'utilise ça:
`[self performSelectorOnMainThread:@selector(updateTable) withObject:_tableView waitUntilDone:NO];
}
- (void)updateTable:(NSTableView *)table {
[table reloadData];
}`
Tout rentre dans l'ordre...
Un idée ?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Peut-être que
[_tableView reloadData];
est appelé depuis un thread secondaire ?Il faudrait voir un peu plus de code.
Si tu forces l'appel dans le main thread (toute update d'UI devrait être fait dans le main thread), c'est sûrement ça le problème.
Pourrais-tu regarder chaque appel de
[_tableView reloadData];
, et vérifier que tu es bien dans le main thread en faisant par exemple avant chaque :NSLog("Will call reloadData from %@", [NSThread isMainThread] ? "main thread" : "background");
Vivi, je fais tout dans le main thread, c'est ce que je comprend pas
J'ai mis Direct: à l'endroit du reload qui bug
Indirect pour en passant par la méthode qui ne bug pas
2019-04-05 11:49:48.857611+0200 MPD Client[51560:18244648] Direct: Will call reloadData from main thread
2019-04-05 11:49:48.863318+0200 MPD Client[51560:18244648] Indirect: Will call reloadData from main thread
La version complète:
(void)awakeFromNib {
// ne pas recharger directement sinon bug à la seconde ligne qui s'affiche à l'envers
[self performSelectorOnMainThread:@selector(updateTable withObject:_streamTableView waitUntilDone:NO];
NSLog(@Direct: Will call reloadData from %s, [NSThread isMainThread] ? "main thread" : "background");
}
(void)updateTable:(NSTableView *)table {
[table reloadData];
NSLog(@Indirect: Will call reloadData from %s, [NSThread isMainThread] ? "main thread" : "background");
}
J'éviterai de faire ça dans
awkeFromNib
et je préfèrerai unviewDidLoad
ou autreviewDidAppear
Si je fais ça ça ne met pas à jour quand je scroll. La partie à l'écran s'affiche correctement et dès que je scroll c'est tout blanc.
Ouais je pense que le texte affiché à l'envers n'est qu'un symptôme d'un tout autre soucis dans ce cas là...
Publie ton code sur GitHub qu'on y regarde.
Tu "nourris" le TableView comment ? Avec un dataSource et delegate ?
Le fichier en question:
https://github.com/Old-Geek/MPD-Client/blob/master/MPD Client/Views/Stream/StreamView.m
https://github.com/Old-Geek/MPD-Client
Evite de regarder l'historique, ça fait 2 jours que je fais l'andouille avec Codebeat pour faire grimper ma note (ça m'aide à penser de façon différente pour avoir d'autres angles de vue).
En voila une bonne question T'aura la réponse avec le lien que je viens de donner.
Ouais c'est bien ce que je dis, essaye de mettre ce code dans
viewDidAppear
Effectivement, ça ne fait pas ce bug dans un
viewDidAppear
mais y'a toujours ce problème de "scroll blanc"C'est certainement lié mais quand je créé une table, avec le truc pour faire l'interface graphique, y'a toujours un label par défaut dans une cellule "Table View Cell". C'est ce qui apparaît à la place du blanc si je le laisse en place.
Ce n'est pas mieux mais si je le laisse et quand je scroll rapidement, ça m'affiche d'abord "Table View Cell" pour changer aussitôt en mon texte.
Ca a aussi la fâcheuse tendance à "scintiller" entre "Table View Cell":"Mon texte" si la cellule n'est pas pleinement visible à l'écran. S'il n'y a que la moitié ou les 3/4 de la cellule d'affiché ça aura tendance à scintiller.
En supprimant le texte "Table View Cell" par défaut, ce problème ne se pose plus.
Je pense que je m'y prend comme un pied quelque part mais internet est loin d'être un bon professeur. Tu trouves du code et de la doc pour apprendre mais c'est fait par des amateurs et les pro ne mettent pas leur gagne pain en ligne, ce qui se comprend très bien, ça n'aide pas forcément à faire les choses correctement.
Et je passe sur la réputation des dévellopeurs qui se confirme assez rapidement même si c'est pas dans la globalité
Commençons par ça dans
StreamView.m
(qui entre nous devrait s'appelerStreamViewController.m
mais passons), dans la méthode- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
:Cette ligne fait bien du mal, parce qui si on regarde la doc :
Voilà pourquoi il ne faut pas mettre de code de rafraichissement de table dans
awakeFromNib
.Pour le reste il faudrait analyser plus en profondeur.
C'est pour cette même raison que je mets ça dans
awakeFromNib
mais je trouvais étrange le fonctionnement, qu'il n'y ait pas d'anticipation de la lecture des datas juste avant de les afficher ne fais pas du tout sérieux.Le plus bizarre c'est que dans la doc d'apple:
Important
It’s possible that your data source methods for populating the table view may be called before awakeFromNib is called if the data source is specified in Interface Builder. You should defend against this by having the data source’s numberOfRowsInTableView: method return 0 for the number of rows when the data source has not yet been configured. In awakeFromNib, when the data source is initialized you should always call reloadData on the table view.
Ma façon de faire est clairement pas la bonne mais interface builer me donne des boutons. J'ai jamais vu un truc aussi mal fichu et peu intuitif... Pourtant dans le monde *nix tout est toujours d'une logique telle que tu peux deviner beaucoup de chose sans même regarder le manuel. Sur ce coup on croirait presque qu'ils ont recruté chez Microsoft pour tout rendre complexe volontairement.
J'ai mis ça en cell based plutot qu'en view based et ça fonctionne beaucoup mieux (plus de awaike).
Fais ça a avec les bindings c'est bien plus simple..