Lancer un algorithme complexe avec un NSButton

Babacool51Babacool51 Membre
décembre 2013 modifié dans Objective-C, Swift, C, C++ #1

Bonjour,

 

Milles excuses pour la question qui va suivre, je suis un parfait débutant en Obj-C. La solution va sans doute vous paraà®tre évidente.

 

J'ai mis au point un algorithme en C qui permet de résoudre un Rubik's Cube 2x2x2 par la force brute. Cela fonctionne parfaitement. Je me suis alors mit en tête de le doter d'un interface (ce que je n'avais jamais essayé de faire auparavant).

 

J'ai donc réussi (dans la douleur) à  concevoir un interface composé de 24 boutons carrés qui changent de couleur quand on clique dessus, et qui servent à  saisir l'état initial du cube. J'ai programmé cela de façon très sale, mais ça fonctionne (variables globales). J'ai également un NSButton "Go !" qui appelle une methode "go" qui contient en fait l'algorithme. 

 

Celle-ci et sensée inscrire dans un NSTextView des informations pendant le déroulement de l'algorithme (genre "Pas de solution en 2 coups","Pas de solution en 3 coups",etc... et enfin "La séquence est blablabla" quand l'algorithme se termine). Sauf que toutes ces lignes de textes s'inscrivent en fait d'un coup toutes en même temps une fois que l'algorithme se termine (donc que l'on sort de la méthode "go"). Pendant le calcul, la NSTextView reste vide (et d'ailleurs le NSButton reste enfoncé ce qui est très moche). Remarquez que j'ai couplé chaque saisie dans la NSTextView avec une saisie dans NSLog qui, elle, fonctionne.




- (IBAction)go:(id)sender;
{
//Algorithme de résolution du cube
//Contient par exemple la ligne [textConsole insertText:@La séquence est : ];
}

 

textConsole étant l'IBOutlet de la NSTextView.

 


Mon souci est clairement un problème de multitasking. Mais je n'ai pas la moindre idée dont je peux m'y prendre pour le résoudre.


 


Merci d'avance =D .


Réponses

  • mpergandmpergand Membre
    décembre 2013 modifié #2

    Salut,


     


    Il te faut créer un thread.


    Il existe plusieurs façons de le faire, la doc est ici:


    https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html


     


    Pour faire simple on peut envisager cette méthode:



    - (IBAction) buttonAction:(id)sender
    {
    [NSApplication detachDrawingThread:@selector(go) toTarget:self withObject:nil];
    }

    // cette méthode s'exécute dans un thread secondaire
    -(void) go
    {
    //Algorithme de résolution du cube
    //Contient par exemple la ligne [textConsole insertText:@La séquence est : ];
    }


    Envoyer des messages à  un contrôle (ici NSTextView) à  partir d'un thread secondaire n'est pas conseillé ( ça peut planter).


    Pour y remédier va falloir que tu lises la doc ;)


     


    Sinon, on peut y arriver sans thread, en jouant avec la runloop, mais c'est une autre histoire ...


  • Merci, c'est exactement ce que je voulais =D .


  • AliGatorAliGator Membre, Modérateur
    "[textConsole insertText:...]" va forcément finir par planter s'il n'est pas exécuté sur le main thread comme mentionné par mpergand. Car toute opération d'UI doit être exécuté sur la RunLoop du thread principal (étant donné que c'est la seule qui gère l'UI et que les classes d'UI ne sont pas thread-safe). Donc il faut déporter ces appels sur le mainThread.


    GCD n'existe pas sur OSX ? (à  force de faire de l'iOS je sais plus ce qui existe sur OSX ^^) parce que ça simplifierai les choses (surtout qui si Babacool51 vient du C ça va pas le dépayser ;-))


    Donc tu crées une dispatch_queue_t (nommons là  workingQueue) qui sera la file GCD sur laquelle seront exécutées les opérations / le code de ton algo, et quand tu as de l'UI à  faire, tu dispatches juste le bout de code lié à  l'UI dans la dispatch_queue_t du mainThread, puis tu continues le reste de ton algo.

    dispatch_async(workingQueue, ^{
    // algo C pour faire tes calculs
    // et quand tu as besoin de faire des opérations sur l'UI, comme remplir ton textView :
    dispatch_async(dispatch_get_main_queue(), ^{
    [textConsole insertText:...];
    });
    // et ensuite tu continues l'algo de calcul (sur la workingQueue donc)
    });
Connectez-vous ou Inscrivez-vous pour répondre.