asynchronisme

bofybofy Membre
02:55 modifié dans API AppKit #1
Bonjour

Dans mon main j'ai
<br />	OpenSPanel * openSPanel = [[OpenSPanel alloc] init]; // OpenSPanel est un NSOpenPanel<br />	[openSPanel showSheet:win];<br />	NSLog(@&quot;file-open:?&quot;);<br />


Le NSLog est toujours exécuté avant même que showSheet soit appelé.
Y a-t-il un moyen de faire en sorte que le NSLog ne soit appelé qu'après l'exécution complète de showSheet ?

Plus généralement, comment synchroniser des instructions ObjC, même complexes ?

Merci

Réponses

  • MalaMala Membre, Modérateur
    02:55 modifié #2
    Regardes plutôt du côté des méthodes suivante:

    <br />- (NSInteger)runModalForDirectory:(NSString *)path file:(NSString *)name types:(NSArray *)fileTypes;<br />- (NSInteger)runModalForTypes:(NSArray *)fileTypes;<br />
    


    Elles attendent le retour d'exécution du panel.
  • MalaMala Membre, Modérateur
    02:55 modifié #3
    dans 1233065820:

    Plus généralement, comment synchroniser des instructions ObjC, même complexes ?


    Les classes gérant des fenêtres ou des panneaux ont des méthode synchrones ou asynchrones donc cela se résume à  appeler le bon code. C'est pas plus compliqué.
  • AliGatorAliGator Membre, Modérateur
    02:55 modifié #4
    showSheet est une méthode asynchrone pour afficher la fenêtre feuille. C'est normal qu'elle soit asynchrone et que tu vois ton NSLog immédiatement.
    Si tu veux continuer à  utiliser le mode asynchrone mais prévoir les méthodes, il faut utiliser les méthodes de delegate (cf ici dans la doc)
    Mais sinon le plus simple c'est d'afficher la fenêtre en modale, via des méthodes comme runModalForTypes :
    [openSPanel runModalForTypes:nil]
    

  • bofybofy Membre
    02:55 modifié #5
    Je crois avoir (presque) compris

    Le code suivant est-il correct :
    <br />	// win est la fenêtre où j&#39;attache le openPanel<br />&nbsp; &nbsp; &nbsp;  NSOpenPanel * panel = [NSOpenPanel openPanel];<br />	[panel beginSheetForDirectory:nil file:nil types:nil modalForWindow:win modalDelegate:nil &#092;<br />						didEndSelector:@selector(didEndOpenSheet:returnCode:contextInfo:) contextInfo:nil];<br />	int sts;<br />	NSMutableString * fln = [[NSMutableString alloc] init];<br />	if ((sts=[panel runModalForTypes:nil])==NSOKButton) { [fln appendString:[panel filename]]; NSLog(@&quot;file open : %@&quot;, fln);}<br />	else if(sts==NSCancelButton) { [fln appendString:@&quot;&quot;]; NSLog(@&quot;cancel&quot;);}<br />	NSLog(@&quot;file-open:?&quot;);<br />
    


    Le "file-open ?" apparaà®t bien après après l'un ou l'autre des NSLog du if.

    Mais le didEndOpenSheet est-elle une méthode de la classe NSOpenPanel ? A quoi sert-elle et où en trouve-t-on la définition ?

    Merci
  • AliGatorAliGator Membre, Modérateur
    02:55 modifié #6
    Ben c'est la méthode de delegate que tu demandes d'appeler quand le NSOpenPanel est fermé !
    Donc c'est à  toi de la définir !!
    Tu crées une méthode, qui aura pour vocation d'être appelée lorsque ta sheet se fermera, pour traà®ter le résultat (récupérer les fichiers que l'utilisateur a choisi dans son panel d'ouverture de fichier, et en faire ce que tu veux), et tu l'appelles par exemple toto... Et ensuite quand tu appelles "beginSheetForDirectory:... file:... types:... modalForWindow:... modalDelegate: xxx didEndSelector: yyy contextInfo:..." ben tu lui indiques avec yyy la méthode à  appeler lorsque le NSOpenPanel est fermé (donc toto dans l'exemple plus haut si tu as appelé ta méthode comme ça... ou didEndOpenSheet si tu l'as nommée comme ça ce qui est plus parlant, mais bon tu lui mets le nom que tu veux) et avec xxx l'objet sur lequel appeller cette méthode (en general self, enfin selon là  où tu as défini ton @selector.
  • bofybofy Membre
    02:55 modifié #7
    Bon, il faut utiliser les delegate auxquels je n'ai toujours rien compris faute de doc pour les ignares.

    Mais mon code, est-il débile ?

    dans 1233249637:

    Ben c'est la méthode de delegate que tu demandes d'appeler quand le NSOpenPanel est fermé !
    Donc c'est à  toi de la définir !!
    Tu crées une méthode, qui aura pour vocation d'être appelée lorsque ta sheet se fermera, pour traà®ter le résultat (récupérer les fichiers que l'utilisateur a choisi dans son panel d'ouverture de fichier, et en faire ce que tu veux), et tu l'appelles par exemple toto... Et ensuite quand tu appelles "beginSheetForDirectory:... file:... types:... modalForWindow:... modalDelegate: xxx didEndSelector: yyy contextInfo:..." ben tu lui indiques avec yyy la méthode à  appeler lorsque le NSOpenPanel est fermé (donc toto dans l'exemple plus haut si tu as appelé ta méthode comme ça... ou didEndOpenSheet si tu l'as nommée comme ça ce qui est plus parlant, mais bon tu lui mets le nom que tu veux) et avec xxx l'objet sur lequel appeller cette méthode (en general self, enfin selon là  où tu as défini ton @selector.
  • bofybofy Membre
    02:55 modifié #8
    dans 1233066828:

    dans 1233065820:

    Plus généralement, comment synchroniser des instructions ObjC, même complexes ?


    Les classes gérant des fenêtres ou des panneaux ont des méthode synchrones ou asynchrones donc cela se résume à  appeler le bon code. C'est pas plus compliqué.


    Je n'ai pas trouvé dans la doc la mention async. ou sync. des méthodes.
    C'est un peu facile de dire que cela se résume à  appliquer le bon code...

    Peux-tu me fournir la liste des méthodes synchrones de NSAlert ?
    Sinon où puis-je la trouver ?
  • NoNo Membre
    02:55 modifié #9
    dans 1242130952:

    Je n'ai pas trouvé dans la doc la mention async. ou sync. des méthodes.
    C'est un peu facile de dire que cela se résume à  appliquer le bon code...
    Peux-tu me fournir la liste des méthodes synchrones de NSAlert ?
    Sinon où puis-je la trouver ?


    Le terme sync ou async est galvaudé ici.

    Pour reprendre ton premier exemple, il faut comprendre qu'il y a 2 choses dans l'affichage d'un panel :
    - son affichage (et seulement ça) à  l'écran,
    - sa gestion des évènements  (avec blocage de la fenêtre principale ou de l'appli).

    Il te manque donc toutes les méthodes qui vont faire tourner le panel en mode modal (blocage de la fenêtre ou de l'appli entière).

    L'exemple que tu donnes dans le premier post est très étrange.
    Ca ressemble à  une sous classe de NSSavePanel ou NSOpenPanel.
    Mais son emploi est alors contraire à  ce que dit la doc Apple au sujet de ces 2 classes.
  • AliGatorAliGator Membre, Modérateur
    02:55 modifié #10
    Pour des dialogues, on parle de dialogues modaux ou non modaux.
    les dialogues modaux (application-modal) bloquent l'application, et ne lui rendent la main que lorsque l'utilisateur a fait disparaà®tre la boite de dialogue. Un dialog non modal s'affiche sans bloquer l'application, qui continue de "vivre sa vie". On peut avoir des dialogues "window-modal" c'est à  dire qui bloquent l'interaction avec la fenêtre à  laquelle ils sont attachés, mais ça ne bloquera pas le reste de l'application pour autant, donc du point de vue de l'application, ils seront non-modaux (asynchrones si tu préfères).


    A partir de là , et surtout du fait qu'en toute logique et par définition, un appel synchrone va forcément te retourner le résultat (bouton cliqué typiquement) immédiatement (en retour de ton appel de fonction, puisque l'appel de fonction aura bloqué ton code jusqu'à  ce que l'utilisateur valide le dialogue), alors qu'un appel asynchrone, puisqu'il va continuer ensuite d'exécuter le reste de ton code, ne pourra te fournir la réponse qu'en appelant une callback, plus exactement un sélecteur (une méthode Objective-C) particulière pour t'informer quand l'utilisateur a fermé le dialogue et te fournir le bouton sur lequel il a cliqué... bah le reste me parait clair :
    - runModal affiche le dialogue de façon application-modal (c'est dit dans la doc) et retourne en retour directement le bouton cliqué : du coup il ne peux être que synchrone, pour pouvoir te retourner le résultat en retour, et parce que par définition il est application-modal.
    - beginSheetModalForWindow affiche le dialogue (sous forme de "sheet" attachée à  une fenêtre, donc certes window-modal, mais) de façon non modale pour l'application. De plus, la méthode demande de passer un "didEndSelector", ce qui comme son nom et surtout la doc l'indique, est le selecteur qui sera appelé lorsque l'utilisateur finira par cliquer sur le bouton, et t'indiquera le bouton cliqué. beginSheetModalForWindow ne te retourne pas lui-même le bouton cliqué, pour la simple et bonne raison qu'il ne peut pas... puisque vu les explications que je viens de donner, ça veut forcément dire que c'est un affichage asynchrone, puisque tu reçois le résultat plus tard via une callback (enfin via une autre méthode appelée à  la fin du dialogue).

    Bref, c'est p'tet pas indiqué noir sur blanc dans la doc et avec le mot "synchrone" et "asynchrone" (d'autant qu'ils ne sont pas forcément adaptés dans le contexte des NSAlert), mais c'est quand même plutôt clair : tu n'as pas 36 méthodes dans la doc concernant "Displaying alerts", et si tu lis la description de chacune pour comprendre leurs différences et quand utiliser l'une ou l'autre, tu as ta réponse  ;)
  • psychoh13psychoh13 Mothership Developer Membre
    02:55 modifié #11
    dans 1233327602:

    Bon, il faut utiliser les delegate auxquels je n'ai toujours rien compris faute de doc pour les ignares.

    Mais mon code, est-il débile ?


    Oui, il ne faut pas sous-classer NSOpenPanel ou NSSavePanel, surtout parce que ce sont des singletons, c'est-à -dire des objets alloués une seule fois puis réutiliser dans différentes occasions.

    La bonne technique c'est d'utiliser le delegate.
  • bofybofy Membre
    02:55 modifié #12
    Bon je crois que je commence à  comprendre.

    En utilisant runModal (application modal) je fais ce que je veux (apparemment...)

    Mais c'est pas joli, car pas associé à  la fenêtre. N'y a-t-il pas un moyen avec beginSheetModalForWindow de suspendre l'exécution du reste de l'application, avec un wait, sleep ou autre ? une sorte de sémaphore ? une notification ?

    Grand merci en tout cas.

    dans 1242133034:

    Pour des dialogues, on parle de dialogues modaux ou non modaux.
    les dialogues modaux (application-modal) bloquent l'application, et ne lui rendent la main que lorsque l'utilisateur a fait disparaà®tre la boite de dialogue. Un dialog non modal s'affiche sans bloquer l'application, qui continue de "vivre sa vie". On peut avoir des dialogues "window-modal" c'est à  dire qui bloquent l'interaction avec la fenêtre à  laquelle ils sont attachés, mais ça ne bloquera pas le reste de l'application pour autant, donc du point de vue de l'application, ils seront non-modaux (asynchrones si tu préfères).


    A partir de là , et surtout du fait qu'en toute logique et par définition, un appel synchrone va forcément te retourner le résultat (bouton cliqué typiquement) immédiatement (en retour de ton appel de fonction, puisque l'appel de fonction aura bloqué ton code jusqu'à  ce que l'utilisateur valide le dialogue), alors qu'un appel asynchrone, puisqu'il va continuer ensuite d'exécuter le reste de ton code, ne pourra te fournir la réponse qu'en appelant une callback, plus exactement un sélecteur (une méthode Objective-C) particulière pour t'informer quand l'utilisateur a fermé le dialogue et te fournir le bouton sur lequel il a cliqué... bah le reste me parait clair :
    - runModal affiche le dialogue de façon application-modal (c'est dit dans la doc) et retourne en retour directement le bouton cliqué : du coup il ne peux être que synchrone, pour pouvoir te retourner le résultat en retour, et parce que par définition il est application-modal.
    - beginSheetModalForWindow affiche le dialogue (sous forme de "sheet" attachée à  une fenêtre, donc certes window-modal, mais) de façon non modale pour l'application. De plus, la méthode demande de passer un "didEndSelector", ce qui comme son nom et surtout la doc l'indique, est le selecteur qui sera appelé lorsque l'utilisateur finira par cliquer sur le bouton, et t'indiquera le bouton cliqué. beginSheetModalForWindow ne te retourne pas lui-même le bouton cliqué, pour la simple et bonne raison qu'il ne peut pas... puisque vu les explications que je viens de donner, ça veut forcément dire que c'est un affichage asynchrone, puisque tu reçois le résultat plus tard via une callback (enfin via une autre méthode appelée à  la fin du dialogue).

    Bref, c'est p'tet pas indiqué noir sur blanc dans la doc et avec le mot "synchrone" et "asynchrone" (d'autant qu'ils ne sont pas forcément adaptés dans le contexte des NSAlert), mais c'est quand même plutôt clair : tu n'as pas 36 méthodes dans la doc concernant "Displaying alerts", et si tu lis la description de chacune pour comprendre leurs différences et quand utiliser l'une ou l'autre, tu as ta réponse  ;)
  • mpergandmpergand Membre
    mai 2009 modifié #13
    Tout est possible  ;)

    <br />- (IBAction) saveButtonAction:(id)sender<br />{	<br />	NSSavePanel* panel=[NSSavePanel savePanel];<br />	[panel beginSheetForDirectory:nil file:@&quot;ff&quot; types:nil modalForWindow:window<br />						modalDelegate: self didEndSelector:@selector(savePanelDidEnd: returnCode: contextInfo:) contextInfo:&nbsp; nil];<br /><br />	int retCode=[NSApp runModalForWindow:panel];<br />	<br />	printf(&quot;ret %d&#092;n&quot;,retCode);<br />	<br />}<br /><br />- (void)savePanelDidEnd:(NSSavePanel *)savePanel returnCode:(int)returnCode&nbsp; contextInfo:(void&nbsp; *)contextInfo;<br />{<br />	[NSApp stopModalWithCode:returnCode];<br />}
    


    Avec OpenPanel ça marche aussi, mais on peut quitter l'application.


  • laudemalaudema Membre
    02:55 modifié #14
    dans 1242302716:

    N'y a-t-il pas un moyen avec beginSheetModalForWindow de suspendre l'exécution du reste de l'application, avec un wait, sleep ou autre ? une sorte de sémaphore ? une notification ?


      La question du néophyte: pourquoi tu veux faire ça ?
    Tu as déjà  une méthode qui sleep et wait : celle que tu mets dans didEndSelector (ou alors je n'ai vraiment rien compris); autrement dit, pour moi, après [NSapp beginSheetModal ... il n'y a rien, la suite est dans endSheetSelector. Sauf pour ce qui se passe à  l'intérieur de la feuille-modale: tu peux avoir dans celle ci des objets qui ont des actions, mais justement ça n'est pas juste après que la feuille soit fermée...

    Cordialement,

    Laurent, pur neophyte
  • laudemalaudema Membre
    02:55 modifié #15
    dans 1233327602:

    Bon, il faut utiliser les delegate auxquels je n'ai toujours rien compris faute de doc pour les ignares.

    Le livre de Hillegas m'a bien servi pour ça.
    Un delegate est un moyen de recevoir (ou renvoyer) des informations d'un autre objet sans le "sous-classer". Pour l'instant je les défini dans IB: par exemple Application a un outlet 'delegate' dans IB tu tires une connexion depuis cet outlet jusqu'à  l'objet que tu veux utiliser comme delegate, chez moi AppController. Alors dans AppController si j'écris une des méthodes delegate de NSApplication elle sera exécutée. Par exemple si tu veux que l'appli quitte une fois la dernière fenêtre fermée tu utilises "- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender;" et tu mets "YES".
    Dans ton cas une fenêtre peut aussi avoir un delegate. Si c'est ta fenêtre feuille tu pourras l'utiliser pour les méthodes des objets à  l'intérieur de la fenêtre, donc dans le "pendant", c'est aussi là  que tu mettras ta methode qui correspond à  didEndSelector.
    Il y a des methodes delegate pour un tas d'objets Cocoa: Application, Fenêtre, VueTableau, Alerte...voir dans le livre de A Hillegass P 108) et tu peux créer les tiennes pour tes objets être utilisés par d'autres objets..

    hth
  • AliGatorAliGator Membre, Modérateur
    02:55 modifié #16
    dans 1233327602:
    Bon, il faut utiliser les delegate auxquels je n'ai toujours rien compris faute de doc pour les ignares.
    Dites, faudrait voir à  chercher parfois, aussi  ;D

    Je vais sur l'ADC, je regarde dans les Guides "Cocoa Fondamentals", et en cherchant un peu je trouve tout ce qu'il faut... n'oubliez pas tous les Guides disponibles dans la doc Apple, y'a pas que les documentations sur les classes elles-mêmes, y'a aussi plein de ressources et sample codes et tout  ;)

    Design Patterns: Delegation et surtout Delegates and Data Sources
Connectez-vous ou Inscrivez-vous pour répondre.