Xcode OS X - Rafraîchir l'affichage à chaque itération ?

les_innommables66

Membre expert
Club iGen
26 Février 2006
1 314
162
Bonjour,

Je voudrais afficher un indicateur d'avancement dans une fenêtre pendant que le programme fait une boucle.

Or le rafraichissement de la fenêtre ne se fait qu'une fois la boucle finie.

Voir l'image du projet ici

Qu'est-ce que je rate ? Comment "forcer" la mise à jour de l'affichage à chaque aération de la boucle ? (j'ai déjà essayé plusieurs solutions, sans succès, cf. les lignes commentées)

Cordialement,
Nicolas
 
Bonjour,

Bloc de code:
@IBACTION 
{

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        // votre travaille
        for (...) {
            // 
            dispatch_async(dispatch_get_main_queue()) {
                view.setNeedsDisplay()
            }
        }
    }
   
}
 
Bonjour,

quelques précisions qui répondront à vos diverses interrogations, d'ailleurs nous avons, il me semble déjà abordé ces questions dans un autre fil concernant Applescript et l'exécution de processus en tâche de fond:

Bloc de code:
@IBACTION
{
Contrôle reçoit l'action de l'utilisateur: UI Thread ou Main Thread.
Il serait bien de bloquer l'état du bouton ici.
Bloc de code:
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
Traitement dans un autre thread voir "concurrency"
https://en.wikipedia.org/wiki/Concurrency_(computer_science)
Bloc de code:
        for (...) { // iteration traitement des données
Il pourrait y avoir un test afin de ne pas demander le rafraichissement à chaque boucle car inutile: la période de rafraichissement étant environ toutes les 33 milliseconds ou 3 fois par 100 ms. Note: pour un utilisateur moyen, un sentiment de "lagging" apparait environ à 210 ms (5 à 7 rafraichissements manqués), CAD, vous bloquez le Main Thread ou/et faites des traitements trop lourds et longs qui n'ont pas leurs places dans celui-ci.
Nous sommes dans un block-concurrent ; tout événement lié à l'interface graphique doit être appelé depuis le Main/UI Thread : depuis ce contexte-concurrent postons un message à celui-ci dispatch_get_main_queue())
Bloc de code:
            dispatch_async(dispatch_get_main_queue()) {
Main/UI Thread runs:
Bloc de code:
                view.setNeedsDisplay()
setNeedsDisplay filtrera si l'UI peut se rafraîchir ou pas "see période", ne jamais appeler display() dans ce genre de contexte : voir documentation.
Bloc de code:
            }
sortie de la boucle:
Bloc de code:
          dispatch_async(dispatch_get_main_queue()) { // unblock button }

        }
Donc, dans votre code donné, vous ne pouvez traiter des données dans l' UI Thread ou Main Thread et espérer le rafraichissement, en effet, vous occupez ce Thread ; le rafraichissement arrive donc après la boucle comme si vous étiez dans un language de script ou les instructions arrivent et s'exécutent dans l'ordre ou elles sont écrites.
Bloc de code:
    }
}

Cordialement.
 
Dernière édition: