Bug avec TableView/OutlineView

avril 2019 modifié dans API AppKit #1

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 ?

Réponses

  • muqaddarmuqaddar Administrateur

    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");

  • avril 2019 modifié #4

    Vivi, je fais tout dans le main thread, c'est ce que je comprend pas

    @Larme a dit :wink:
    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");

    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:

  • J'éviterai de faire ça dans awkeFromNib et je préfèrerai un viewDidLoad ou autre viewDidAppear

  • @Pyroh a dit :
    J'éviterai de faire ça dans awkeFromNib et je préfèrerai un viewDidLoad ou autre viewDidAppear

    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.

  • @Harlo a dit :

    @Pyroh a dit :
    J'éviterai de faire ça dans awkeFromNib et je préfèrerai un viewDidLoad ou autre viewDidAppear

    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.

  • Joanna CarterJoanna Carter Membre, Modérateur
    avril 2019 modifié #8

    Tu "nourris" le TableView comment ? Avec un dataSource et delegate ?

  • avril 2019 modifié #9

    @Pyroh a dit :smile:
    Publie ton code sur GitHub qu'on y regarde.

    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).

    @Joanna Carter a dit :
    Tu "nourris" le TableView comment ? Avec un dataSource et delegate ?

    En voila une bonne question :smiley: 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

  • avril 2019 modifié #11

    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é :D

  • Commençons par ça dans StreamView.m (qui entre nous devrait s'appeler StreamViewController.m mais passons), dans la méthode - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row :

    NSTableCellView *cell = [tableView makeViewWithIdentifier:@"name" owner:self];
    

    Cette ligne fait bien du mal, parce qui si on regarde la doc :

    Note that awakeFromNib is called each time this method is called, which means that awakeFromNib is also called on owner, even though the owner is already awake.

    Voilà pourquoi il ne faut pas mettre de code de rafraichissement de table dans awakeFromNib.

    Pour le reste il faudrait analyser plus en profondeur.

  • avril 2019 modifié #13

    @Pyroh a dit :
    Cette ligne fait bien du mal, parce qui si on regarde la doc :

    Note that awakeFromNib is called each time this method is called, which means that awakeFromNib is also called on owner, even though the owner is already awake.

    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..

Connectez-vous ou Inscrivez-vous pour répondre.