gestion des delegations

alain.lcalain.lc Membre
08:01 modifié dans API AppKit #1
bonjour

j'ai beaucoup de mal à  cerner le fonctionnement des délégations et je ne trouve rien sur le net qui puisse m'aider de façon clair.
un exemple concret avec une appli "utilitaire" sous xcode, elle contient 2 vue (MainView et SlideView) gérer par RootViewController qui permet de deleguer des
actions (toogleView en l'occurence)

ce que je cherche à  faire c'est une troisieme vue (testView) qui puisse lancer une fonction contenu dans MainView, et là  je m'arrache les cheveux

ou est-ce que je pourrai trouver un tuto qui m'aiderai à  comprendre les Delegate ?

d'avance merci
«1

Réponses

  • Philippe49Philippe49 Membre
    octobre 2008 modifié #2
    Je ne connaà®s pas de tuto sur ce sujet, mais on peut répondre à  tes questions.

    Le delegate est en soi quelque chose de simple. Lorsqu'une instance ayant un delegate pour un certain nombre de messages  reçoit l'un de ces messages, il le fait exécuter à  son delegate. C'est tout.

    un message = une demande d'exécution de méthode
  • alain.lcalain.lc Membre
    08:01 modifié #3
    d'abord merci de prendre du temps pour me répondre :)

    je pense avoir compris plus ou moins mais c'est encore flou,
    dans mon cas mon appli (sur la base d'une template xcode pour iphone) à  une vue (MainView et SlideView qui ont deja comme delegue : rootViewControler)
    à  cela moi j'ajoute testView qui à  egalement rootViewControler en delgué ...
    tout fonctionne nickel.
    Maintenant je cherche à  ajouter un DEUXIEME delegué à   testView car il faut qu'elle execute une procedure de MainView
    et la je melange tout :(, plus rien ne marche
  • NoNo Membre
    08:01 modifié #4
    dans 1223476016:

    Maintenant je cherche à  ajouter un DEUXIEME delegué à Â  testView car il faut qu'elle execute une procedure de MainView

    A quelques exceptions près, un objet ne peut pas avoir de DEUXIEME delegate.
    Si tu tentes une telle manip (par code ou dans IB), le premier sera remplacé par le second, ce qui modifiera le comportement de testview.

    dans 1223476016:

    ce que je cherche à  faire c'est une troisieme vue (testView) qui puisse lancer une fonction contenu dans MainView, et là  je m'arrache les cheveux

    Le problème est que testView ne connait pas MainView. Là , la gestion standard de delegate ne peut pas te servir. C'est donc à  toi d'implanter ta propre gestion d'un second delegate par exemple (ou par notification si ça existe sous iPhone), afin de lier les 2 xxViews.
  • Philippe49Philippe49 Membre
    08:01 modifié #5
    dans 1223476016:

    dans mon cas mon appli (sur la base d'une template xcode pour iphone) à  une vue (MainView et SlideView qui ont deja comme delegue : rootViewControler)
    à  cela moi j'ajoute testView qui à  egalement rootViewControler en delgué ...
    tout fonctionne nickel.
    Maintenant je cherche à  ajouter un DEUXIEME delegué à   testView car il faut qu'elle execute une procedure de MainView
    et la je melange tout :(, plus rien ne marche


    J'ai l'impression que l'organisation de ton arborescence de vues demande à  être repensée !

    De plus qu'est-ce qui empêche testView de recevoir le message et de le renvoyer à  mainView ?
    -( .... ) methodeDansTestView .....
      [mainView methodeDansMainView ... ];

    Il suffit que testView ait connaissance de mainView en direct ou par l'intermédiaire de rootViewController ... 

  • mouvicielmouviciel Membre
    08:01 modifié #6
    dans 1223474692:

    Je ne connaà®s pas de tuto sur ce sujet, mais on peut répondre à  tes questions.

    dans 1223466402:

    ou est-ce que je pourrai trouver un tuto qui m'aiderai à  comprendre les Delegate ?

    Bonjour,

    Sur mon blog tout neuf il y a une mini-série de deux articles dans lesquels j'essaie d'aborder la délégation pour les non-confirmés. C'est plutôt orienté Mac et pas iPhone, mais je suppose qu'il n'y a pas trop de différence.
    C'est ici pour la première partie, et là  pour la deuxième partie. J'espère que ça pourra aider...
  • alain.lcalain.lc Membre
    08:01 modifié #7
    dans 1223482170:

    J'ai l'impression que l'organisation de ton arborescence de vues demande à  être repensée !

    Effectivement, j'ai revu mon arborescence (ce qui est je pense la meilleure chose à  faire dans mon cas), sa fonctionne nickel maintenant.

    en tout cas je garde vos conseils pour mes prochaines "delegation" :)

    merci !
  • bofybofy Membre
    08:01 modifié #8
    Bonjour

    cf. le fil asychronisme

    C'est tellement simple qu'il n'y a pas de tuto... N'empêche que je ne comprends rien aux delegate, d'autant qu'ils sont toujours masqués par IB !

    "Lorsqu'une instance ayant un delegate" : comment savoir si une instance a un delegate ? comment reconnaà®tre un delegate ? comment créer un delegate pour une instance ?

    "pour un certain nombre de messages" : où trouver la liste de ces messages ? comment créer un message dans cette liste ?

    "  reçoit l'un de ces messages," : comment récupérer un tel message ? et le faire exécuter par le delegate ad-hoc ?

    "il le fait exécuter à  son delegate" : comment ?

    "C'est tout" : je pense que ton texte décrit parfaitement le fonctionnement des delegate, mais seulement pour des initiés ; il n'explique pas comment faire !


    dans 1223474692:

    Je ne connaà®s pas de tuto sur ce sujet, mais on peut répondre à  tes questions.

    Le delegate est en soi quelque chose de simple. Lorsqu'une instance ayant un delegate pour un certain nombre de messages  reçoit l'un de ces messages, il le fait exécuter à  son delegate. C'est tout.

    un message = une demande d'exécution de méthode
  • AliGatorAliGator Membre, Modérateur
    janvier 2009 modifié #9
    • Alors pour savoir si une classe a un delegate, c'est simple : (1) c'est indiqué dans la doc de ladite classe en général (2) cette classe possède une variable d'instance qui s'intitule précisément "delegate" et est faite pour stocker... l'objet delegate associé à  ton objet.
    • Le "certain nombre de messages", pareil c'est dans la doc, c'est indiqué d'un "delegate method" en face dans la liste des méthodes, et dans la doc les "delegate methods" (méthodes appelées sur "delegate" et non sur l'objet "self" lui-même) sont regroupées.
    • Ce n'est pas à  toi de "récupérer un tel message et le faire exécuter par le delegate", c'est juste que le message est automatiquement envoyé au delegate. Quand on appelle une méthode en Objective-C, pour rappel, on écrit [unObjet uneMethode]. Si tu veux appeler une méthode de ta classe (une méthode "uneMethode" qui est dans la même classe que celle dans laquelle tu écris ton code), tu écris [self uneMethode]. Si tu veux appeler une méthode sur l'objet delegué, tu fais [delegate uneMethode]. C'est ce qui est fait en interne dans les classes qui utilisent les delegate (et à  moins que ce soit toi qui implémente le mécanisme de delegate pour tes propres classes, quand c'est des classes Apple qui utilisent un delegate, c'est donc fait en interne donc appelé tout seul au bon moment)



    Un petit exemple de code t'éclaircira peut-être un peu les idées. Voici un exemple de classe bateau qu'on pourrait implémenter et qui utilise un delegate :
    @interface TestClass : NSObject<br />{<br />  id delegate; // variable d&#39;instance pour stocker l&#39;objet qui servira de &quot;delegate&quot;<br />  int _value; // une variable d&#39;instance bidon pour l&#39;exemple<br />}<br />-(void)setValue:(int)val;<br />@property(nonatomic, retain) delegate;<br />@end<br /><br />@implementation TestClass<br />@synthetize delegate; // créer le setter/getter automatiquement, j&#39;ai pas envie de m&#39;embêter j&#39;ai la flemme et les @property sont là  pour ça :D<br /><br />-(void)setValue:(int)val {<br />  _value = val;<br />  [delegate testClass:self valueHasChangedTo:val]; // hop, on appelle la méthode de delegate.<br />}<br />@end
    
    Voilà  un exemple de classe maison "ayant un delegate" et qui appelle la méthode "testClass:valueHasChanged:" de l'objet delegate quand on change sa "value". C'est pour te donner une idée de la façon dont Apple implémente ça dans ses classes aussi, c'est le même principe. Là  on "prévient le delegate" en quelques sortes quand l'instance a changé sa valeur (c'est qu'un exemple comme un autre), en appelant la méthode de delegate "[tt]testClass: valueHasChanged:[/tt]", en lui passant l'instance de TestClass en premier argument (comme ça on peut retrouver quel est l'objet TestClass qui a changé sa valeur) et la nouvelle valeur.

    Après, si tu as une classe de ce genre et que tu veux l'utiliser, il suffit de prévoir une classe qui implémente la méthode "testClass: valueHasChangedTo:", et de définir le delegate de ta TestClass comme étant l'instance de cette classe qui implémente ta méthode. Exemple :
    @implementation Toto<br />-(void)awakeFromNib<br />{<br />  // faire des trucs<br />  TestClass* t = [[TestClass alloc] init];<br />  t.delegate = self; // définir l&#39;instance courante de Toto comme étant le &quot;delegate&quot; de mon TestClass.<br />  // C&#39;est donc mon instance courante de Toto (self) qui va recevoir les &quot;messages destinés au delegate de TestClass&quot;<br />  [t setValue:5]; // vu comment TestClass est codé, ça va appeler la méthode &quot;testClass: valueHasChangedTo:&quot; de son delegate... donc de mon Toto<br />  [t release];<br />}<br /><br />-(void)testClass:(TestClass*)aTestClass valueHasChangedTo:(int)newValue {<br />  // cette &quot;delegate method&quot; de TestClass est appellée à  chaque fois que mon TestClass (dont je suis le delegate) change sa valeur<br />  NSLog(@&quot;Tiens, l&#39;instance de TestClass %@ a une nouvelle valeur qui vaut maintenant %d !&quot; , aTestClass, newValue);<br />}<br />@end
    
    Voilà , avec cet exemple de code qui utilise TestClass, on définit "self" comme delegate de notre TestClass, donc c'est lui qui "recevra" les "delegate methods" quand TestClass les appellera.


    ----


    Après, en pratique, y'a des cas d'utilisation bien plus intéressants de delegate. Par exemple dans tous les cas asynchrones, quand tu demandes de faire une opération, mais qu'elle se termine "plus tard", souvent y'a une méthode de delegate qui est alors appellée "une fois que l'opération est terminée" pour te prévenir que c'est fini.

    Exemple, quand tu fais une requête asynchrone avec NSURLConnection (une classe qui permet de faire des requêtes vers des URL, par exemple une requête web, sans bloquer ton code pour autant... asynchrone, quoi). Tu crées une NSURLConnection via la méthode [tt]connectionWithRequest:... delegate:...[/tt] qui va directement lancer la requête de manière asynchrone (donc tu récupères la main ensuite et ton code continue)... Mais du coup comme c'est asynchrone il faut un mécanisme pour te prévenir quand la requête a réussi (ou pas), et que le contenu récupéré par la requête est enfin disponible (puisque ça peut mettre un peu de temps le temps de charger l'URL selon la vitesse de ton réseau, etc)... C'est là  qu'intervient le "delegate", que tu as indiqué lorsque tu as créé ton NSURLConnection : c'est à  ce "delegate" que va être envoyé la "delegate method" nommée "[tt]connectionDidFinishLoading:[/tt]" (en gros en interne il appelle [tt][delegate connectionDidFinishLoading:self][/tt] j'imagine), donc toi ce que tu as à  faire c'est de prévoir d'implémenter la méthode "connectionDidFinishLoading:" dans le code de l'objet que tu as fourni en tant que "delegate" de ta NSURLConnection. Et de mettre dedans le code que tu veux exécuter quand ta requête a abouti et que tu veux traiter les données reçues.

    (Bon c'est qu'un exemple, je suis même pas allé voir dans la doc de WebView la signature des vraies méthodes de delegate à  implémenter hein, mais c'est pour que tu voies l'idée)
  • CéroceCéroce Membre, Modérateur
    08:01 modifié #10
    Franchement, vous vous prenez le chou pour rien.

    Un délégué, c'est quoi ?
    Un objet qui est associé à  un autre, qui lui délègue une partie de son fonctionnement.

    Par exemple, allez voir la doc de la classe NSWindow. Elle comporte une rubrique "Delegate methods".
    Imaginons que je veuille bipper à  chaque fois qu'une fenêtre est déplacée. Il faut que mon délégué implémente la méthode windowDidMove:.

    Créons, le délégué:
    <br />#import &lt;Cocoa/Cocoa.h&gt;<br /><br /><br />@interface OCWindowBeepDelegate : NSObject {<br /><br />}<br /><br />- (void)windowDidMove:(NSNotification *)notification;<br /><br />@end<br />
    


    <br />#import &quot;OCWindowBeepDelegate.h&quot;<br /><br /><br />@implementation OCWindowBeepDelegate<br /><br />- (void)windowDidMove:(NSNotification *)notification<br />{<br />	NSBeep();<br />}<br />@end<br />
    


    Ensuite, on crée un objet de type OCWindowBeepDelegate sous IB, et on relie l'outlet delegate de la fenêtre à  cet objet.


    Comment ça fonctionne en pratique:
    - si la fenêtre n'a pas de délégué (son outlet n'est reliée à  rien), elle exécute elle-même la méthode. Le plus souvent, l'implémentation par défaut ne fait rien.
    - sinon, c'est la méthode du délégué qui est appelé.

    L'avantage des délégués, c'est que ça évite de sous-classer.
    Ce concept (helper objects) est très courant sous Cocoa. On le retrouve par exemple pour les data sources qui remplissent les NSTableView.
  • AliGatorAliGator Membre, Modérateur
    08:01 modifié #11
    dans 1233330534:

    Franchement, vous vous prenez le chou pour rien.
    Ben nous on se prend pas la tête c'est qu'il n'arrive pas à  saisir le concept... donc c'est un peu ce qu'on avait expliqué au début mais apparament ça n'avait pas suffit donc c'est pour ça qu'on rentre dans les détails :P

    dans 1233330534:
    - si la fenêtre n'a pas de délégué (son outlet n'est reliée à  rien), elle exécute elle-même la méthode. Le plus souvent, l'implémentation par défaut ne fait rien.
    Heu t'es sûr ? Moi quand je crée des classes qui utilisent un delegate, je vais comme j'ai fait plus haut, j'appelle juste un [delegate maMethodeDeDelegate] dans ma classe au moment où il faut, pour que "maMethodeDeDelegate" soit appelée sur le delegate..; Et si y'a pas de delegate, autrement dit qu'il est nil, bah ça appelle la méthode sur "nil", donc ça fait rien... Pour toi par défaut à  la création de ton objet si tu mets pas de delegate, le delegate est associé à  self, l'instance de l'objet lui-même, donc ? Je n'ai jamais pu constater ce comportement, pour moi quand je met pas de delegate personne ne reçoit la méthode (puisqu'envoyée à  nil)...
  • mouvicielmouviciel Membre
    08:01 modifié #12
    dans 1223466402:

    ou est-ce que je pourrai trouver un tuto qui m'aiderai à  comprendre les Delegate ?


    Bonjour,

    J'ai une paire d'articles sur la délégation dans mon blog. C'est ici pour le premier et là  pour le deuxième.
  • CéroceCéroce Membre, Modérateur
    janvier 2009 modifié #13
    dans 1233331563:

    Et si y'a pas de delegate, autrement dit qu'il est nil, bah ça appelle la méthode sur "nil", donc ça fait rien... Pour toi par défaut à  la création de ton objet si tu mets pas de delegate, le delegate est associé à  self, l'instance de l'objet lui-même, donc ?


    Je n'arrive pas à  retrouver, mais j'ai bien lu dans la doc d'une méthode "l'implementation par défaut fait ça, mais vous pouvez déléguer cette méthode".
    On peut faire autrement que mettre l'outlet delegate à  self, par exemple:

    <br />if(delegate)&nbsp; &nbsp;// delegate est nul si l&#39;outlet n&#39;est reliée à  rien<br />{<br />&nbsp; &nbsp; if([delegate respondsToSelector:@selector(windowDidResize:))<br />&nbsp; &nbsp; &nbsp; &nbsp; [delegate windowDidResize:notification];<br />&nbsp; &nbsp; else<br />&nbsp; &nbsp; &nbsp; &nbsp; [self windowDidResize:notification];<br />}<br />else<br />&nbsp; &nbsp; [self windowDidResize:notification];<br />
    


    De toute façon, on peut penser qu'avoir un délégué et posséder une implémentation par défaut est plutôt rare.
  • bofybofy Membre
    08:01 modifié #14
    Deuxième intervention pour faire de la pub pour ton site.
    C'est très bien, mais tu te précipites sur IB : dès lors on n'a plus aucune chance de rien comprendre...

    dans 1233332728:

    dans 1223466402:

    ou est-ce que je pourrai trouver un tuto qui m'aiderai à  comprendre les Delegate ?


    Bonjour,

    J'ai une paire d'articles sur la délégation dans mon blog. C'est ici pour le premier et là  pour le deuxième.
  • mouvicielmouviciel Membre
    février 2009 modifié #15
    dans 1234021474:

    Deuxième intervention pour faire de la pub pour ton site.
    C'est très bien, mais tu te précipites sur IB : dès lors on n'a plus aucune chance de rien comprendre...


    Je ne pensais pas faire de la pub, je pensais aider. Pardonne-moi si mes interventions ont pu être mal interprêtées.

    Pour ce qui est d'IB, j'appuie mon exemple sur le délégué de NSWindow. Je pensais qu'il serait plus simple de mettre en place l'interface graphique avec IB plutôt qu'avec du code. Peut-être aurais-je dû choisir un autre exemple.

    Merci en tout cas de ton retour.
  • psychoh13psychoh13 Mothership Developer Membre
    février 2009 modifié #16
    En fait, Céroce et AliGator, pour être précis... Un délégateur a en général une méthode centrale qui est appelée lors des opérations impliquant le délégué. cette méthode teste dans le delegate la présence de la méthode impliquée et envoie le message si elle est présente, sinon elle utilise un comportement par défaut, qui en général laisse le programme continuer tout seul. (par exemple: windowShouldClose: en l'absence de délégué, la valeur supposée est YES).

    Au passage, AliGator, tu confonds délégué et notification, les délégués modifient le comportement des objets délégateurs, alors que les notifications préviennent les objets notifiés que quelque chose est arrivée. L'exemple d'implémentation de délégué que tu donnes n'est pas bon.
    Là , le délégateur donnerait plutôt les méthodes : testClass:shouldValueChangeTo: et testClassValueDidChange:
    Dans la première, la méthode retournera soit un booléen ou alors la valeur à  mettre, et pour la deuxième méthode, le premier argument serait une notification contenant comme propriété "object" l'objet ayant envoyé la notification. Il faut remarquer qu'une notification est à  la fois envoyée aux observateurs de la notification mais aussi au délégué de l'objet ayant envoyé la notification.

    Dans le cas de NSURLConnection, c'est un peu spécial, le délégué ne va pas forcément modifier le comportement de l'objet, mais il va en fait suivre son délégateur tout au long de la vie de l'objet et être prévenu pour chacune des modifications du comportement qui intervient, c'est pour ça qu'on a la méthode connectionDidFinishLoading: qui ressemble à  une notification mais qui n'en est pas une.


    Sinon, je me suis amusé à  trifouiller un peu avec la méthode windowShouldClose: de NSWindow en faisant une sous-classe. Après quelques tests voilà  ce qui en ressort:
    - Si le délégué est "nil" ou si il n'implémente pas la méthode windowShouldClose:, la fenêtre a un comportement par défaut, et fait comme si windowShouldClose: retournait YES, en clair la fenêtre se ferme sans que rien d'autre ne se passe.
    - Si le délégué implémente la méthode, alors cette méthode est appelée et la fenêtre se ferme si l'implémentation de windowShouldClose: dans le délégué retourne YES. Jusque là  pas de problème.
    - En revanche, si le délégué est nil ou s'il n'implémente pas la méthode mais que le délégateur implémente cette méthode, alors le délégateur appelle sa propre implémentation et change son comportement selon sa valeur de retour.
    Donc, NSWindow n'implémente pas windowShouldClose:, si on implémente la méthode dans une sous-classe ou bien si on ajoute la méthode à  NSWindow, cette méthode sera appelée si le délégué ne l'implémente pas.

    En clair, une sous-classe, ou une catégorie, peut fournir sa propre implémentation par défaut d'une méthode déléguée... En tout cas pour windowShouldClose:, faut voir après pour les autres méthodes.
  • schlumschlum Membre
    08:01 modifié #17
    Bah, une méthode déléguée ne change pas forcément le comportement de quiconque...
    Il suffit de voir le nombre de méthodes déléguées "(void)...Will...:(NSNotification*)notification" et qui sont couplées à  des notifications.

    Un delegate n'est qu'un objet "callBack" et les méthodes déléguées des "callBacks". Et ça intègre le fait de modifier le comportement de l'objet appelant... ou pas.


    Les notifications, c'est différent sur plusieurs points très importants :
    - ça n'attend pas le retour
    - ça peut envoyer un message à  un objet qui est totalement inconnu de l'envoyeur
  • psychoh13psychoh13 Mothership Developer Membre
    08:01 modifié #18
    Les méthodes déléguées sont celles dont le premier argument est le délégateur, ce qui exclu les notifications, les méthodes en "-(void)...Will...:(NSNotification*)notification", comme l'indique leur premier et seul paramètre, sont des notifications, mais elles sont signalées comme méthodes déléguées tout simplement parce que, pour toute notification, le délégateur envoie la notification directement à  son délégué sans passer par le notification center ; un délégué, et c'est dit explicitement dans la doc, est d'office observeur des notifications envoyées par le délégateur, et donc les notifications, pour des raisons de performance, sont aussi transformées en méthode déléguées, mais elles restent des notifications car leur argument est une NSNotification et non pas l'objet délégant.

    Aussi, les méthodes déléguées ont été créé, et sont là  essentiellement pour ça, pour influer sur le comportement de leur déléguant. Pour ce qui est des méthodes déléguées qui retournent une valeur, là  c'est évident c'est pour influer sur le comportement du déléguant, et même si la méthode consiste à  reproduire le comportement par défaut (genre un return YES; inconditionnel dans -windowShouldClose: ) c'est déjà  une influence.

    Dans le cas des méthodes déléguées qui ne retourne rien, là  c'est plutôt une dérive du concept, cependant, à  l'instar des notifications envoyées aux déléguées directement, ça reste en accord avec le concept ; le délégué étant créé pour suivre le délégateur tout au long de son existence, les méthodes telles que connectionDidFinishLoading: de NSURLConnection rentre dans le même panier que les déléguées sans pour autant être des notifications.
  • schlumschlum Membre
    février 2009 modifié #19
    Et c'est marqué où dans la doc qu'un delegate doit influer sur son appelant ?  :P
    http://developer.apple.com/DOCUMENTATION/Cocoa/Conceptual/CocoaFundamentals/CommunicatingWithObjects/chapter_6_section_4.html

    Tu ne confonds pas avec DataSource par hasard ?


    Les "will" sont aussi appelés par notifications... Ben oui, mais à  la base, ce sont des méthodes déléguées ; le fait que ça soit des notifications aussi ne vient qu'après.

    C'est appelé sur le délégué pour qu'il ait le temps d'agir avant de rendre la main et que l'action soit effectivement faite. Bref, une callback quoi.
  • schlumschlum Membre
    février 2009 modifié #20
    D'ailleurs, toutes ne sont pas des notifications alors qu'elles le pourraient...
    Un exemple parmi d'autres :
    - (NSSize)drawerWillResizeContents:(NSDrawer *)sender toSize:(NSSize)contentSize
    


    Et des exemples de classes qui n'attendent absolument pas en général d'être influencées par leur delegate :
    - NSURLConnection
    - NSURLDownload
    - NSXMLParser
    - NSKeyedArchiver
  • psychoh13psychoh13 Mothership Developer Membre
    08:01 modifié #21
    dans 1234099411:

    Et c'est marqué où dans la doc qu'un delegate doit influer sur son appelant ?  :P
    http://developer.apple.com/DOCUMENTATION/Cocoa/Conceptual/CocoaFundamentals/CommunicatingWithObjects/chapter_6_section_4.html

    Tu ne confonds pas avec DataSource par hasard ?


    Non, non je parle bien des delegates, et c'est écrit dans la documentation : "
    the delegate implements only those methods where it has an interest in coordinating itself with the delegating object or affecting that object's default behavior."


    Et c'est confirmé plus bas dans la partie concernant les datasources :
    "A data source is like a delegate except that, instead of being delegated control of the user interface, it is delegated control of data."


    dans 1234099411:
    Les "will" sont aussi appelés par notifications... Ben oui, mais à  la base, ce sont des méthodes déléguées ; le fait que ça soit des notifications aussi ne vient qu'après.

    C'est appelé sur le délégué pour qu'il ait le temps d'agir avant de rendre la main et que l'action soit effectivement faite. Bref, une callback quoi.


    Sinon j'insistait surtout sur l'argument NSNotification, pas sur le will. Toutes les méthodes ayant pour argument NSNotification sont des notifications, et comme le délégué est d'office considérer comme "observeur" de la notification, les méthodes de notification sont aussi passées en méthodes déléguées.

    dans 1234099702:

    D'ailleurs, toutes ne sont pas des notifications alors qu'elles le pourraient...
    Un exemple parmi d'autres :
    - (NSSize)drawerWillResizeContents:(NSDrawer *)sender toSize:(NSSize)contentSize
    


    Et des exemples de classes qui n'attendent absolument pas en général d'être influencées par leur delegate :
    - NSURLConnection
    - NSURLDownload
    - NSXMLParser
    - NSKeyedArchiver


    Et je confirme que ce sont des méthodes déléguées, du simple fait que leur premier argument et l'envoyeur du message et non pas une NSNotification.
  • mpergandmpergand Membre
    08:01 modifié #22
    dans 1234099411:


    Les "will" sont aussi appelés par notifications... Ben oui, mais à  la base, ce sont des méthodes déléguées ; le fait que ça soit des notifications aussi ne vient qu'après.



    Je dirais que c'est exactement l'inverse  ;)

    par ex, l'object delegate de NSWindow est enregistré pour recevoir toutes les notifs émises par NSWindow.

    For example, the windowDidMove: method is associated with the NSWindow method NSWindowDidMoveNotification. The section “Notifications” discusses notifications in detail, but here it's important to understand the relation of notifications to delegation messages in the Application Kit. The delegating object automatically makes its delegate an observer of all notifications it posts. All the delegate needs to do is implement the associated method to get the notification.

  • psychoh13psychoh13 Mothership Developer Membre
    février 2009 modifié #23
    dans 1234102317:

    dans 1234099411:


    Les "will" sont aussi appelés par notifications... Ben oui, mais à  la base, ce sont des méthodes déléguées ; le fait que ça soit des notifications aussi ne vient qu'après.



    Je dirais que c'est exactement l'inverse  ;)

    par ex, l'object delegate de NSWindow est enregistré pour recevoir toutes les notifs émises par NSWindow.

    For example, the windowDidMove: method is associated with the NSWindow method NSWindowDidMoveNotification. The section “Notifications” discusses notifications in detail, but here it's important to understand the relation of notifications to delegation messages in the Application Kit. The delegating object automatically makes its delegate an observer of all notifications it posts. All the delegate needs to do is implement the associated method to get the notification.




    Je confirme, il suffit de court-circuiter les méthodes -addObserver:selector:name:object:, -removeObserver: et -removeObserver:name:object de NSNotificationCenter pour s'en rendre compte...
    Quand tu donnes un délégué à  une NSWindow, ton objet sera enregistrer comme observeur de toutes les notifications de NSWindow auxquelles il est capable de répondre avec ces fameuses implémentations de méthodes déléguées.
    Et quand tu changes de délégué (ou que tu le mets à  nil) NSWindow retire la totalité des notifications observables (étant donné que retiré un observeur qui n'est pas dans la liste ne pose pas de problème...).

    Donc, si tu veux que ton délégué ne réponde pas aux notifications tout en implémentant les méthodes il te suffit de faire -removeObserver: avec ton délégué en paramètre. ;)

    Conclusion, les méthodes prenant une NSNotification en paramètre sont bien des notifications et non pas méthodes déléguées, le délégateur ne fait que simplifier la procédure pour ces méthodes.
  • schlumschlum Membre
    08:01 modifié #24
    dans 1234101526:

    Non, non je parle bien des delegates, et c'est écrit dans la documentation : "
    the delegate implements only those methods where it has an interest in coordinating itself with the delegating object or affecting that object's default behavior."



    Tu soulignes que ce qui t'intéresses dans la phrase, et pas ce qui est le plus important  :)
    coordinating itself with the delegating object OR ... "
    Oui, c'est bien la définition d'une callback...
    L'objet qui appelle une méthode déléguée en attend le retour pour recevoir l'information :
    - Soit une réponse qui lui permet effectivement d'affecter son comportement
    - Soit pas de réponse qui lui indique juste que l'objet délégué a bien fini de traiter le message

    Contrairement à  une notification qui est balancée et on passe à  la suite en se fichant de savoir si ça a été bien traité ou pas.
  • schlumschlum Membre
    08:01 modifié #25
    dans 1234101526:

    dans 1234099702:

    Et des exemples de classes qui n'attendent absolument pas en général d'être influencées par leur delegate :
    - NSURLConnection
    - NSURLDownload
    - NSXMLParser
    - NSKeyedArchiver


    Et je confirme que ce sont des méthodes déléguées, du simple fait que leur premier argument et l'envoyeur du message et non pas une NSNotification.


    Et pourtant ces méthodes déléguées n'affectent aucunement l'objet qui les appelle contrairement à  ce que tu disais au dessus  ;)
    Elles ne servent que de callbacks de traitement :
    " j'ai récupéré ces données pendant le traitement et je les transmets à  mon objet callback "delegate" "
  • schlumschlum Membre
    février 2009 modifié #26
    dans 1234101526:

    Sinon j'insistait surtout sur l'argument NSNotification, pas sur le will. Toutes les méthodes ayant pour argument NSNotification sont des notifications, et comme le délégué est d'office considérer comme "observeur" de la notification, les méthodes de notification sont aussi passées en méthodes déléguées.


    Pas quand elles sont envoyées au delegate justement ! Parce que ça attend le retour, et c'est une différence énorme...
    Par exemple NSWindow va dire à  son "delegate" : "windowWillClose"... Et le delegate va faire tout plein de traitement avant de retourner ; pendant ce temps la fenêtre attendra sagement la réponse.
    Alors que pour les autres, elle va balancer la notification, puis fermer sans se préoccuper de ce qu'ils en pensent.

    Ce n'est pas qu'une relation d'observation, le "delegate" est actif ! (donc même si l'argument est une NSNotification*, ça ne peut être considéré comme une notification dans le sens des notifications Cocoa).
  • NoNo Membre
    08:01 modifié #27
    Schlum a entièrement raison.
    Le système delegate implanté par les classes cocoa n'est que la traduction "objet" du système des callback utilisés en prog procédurale.

    La différence entre delegate et notification est fondamentale.

    - pour un delegate, l'objet "émetteur", ce dernier interroge s'il a un delegate et s'il implante la bonne méthode. Si oui, il appelle (call) l'objet delegate et attend la fin de l'exécution de la méthode puisque c'est un call. Eventuellement, le delegate peut retourner une valeur (cas par exemple de windowShouldClose de NSWindow) ou modifier l'objet en paramètre (cas de tableView:willDisplayCell:forTableColumn:row: de NSTableView), d'où le terme de callback.

    - pour une notification, l'objet émetteur n'a aucune connaissance du ou DES objets pouvant recevoir les notifs. Pire, la doc Apple indique bien qu'il n'y a aucun synchronisme entre envoi de la notif par l'objet émetteur, et réception par les objets abonnés à  la notification.

    Et c'est normal, car les notifs passe par la boucle d'événement, alors que les delegate ne sont que des appels purs et simples.

    Chaque méthode a donc son avantage :
    - un delagate peut (éventuellement) influancer l'émetteur (puisque appel direct).
    - une notification peut être reçue par une multitude d'objets en même temps.

  • schlumschlum Membre
    février 2009 modifié #28
    En gros pour être plus clair, quand une NSWindow envoie le message "- (void)windowWillClose:(NSNotification *)notification" à  son delegate, ça ne passe pas par un Notifications Center
    -> ce n'est pas une notification (l'appel est direct et attend le retour).

    Le fait que l'argument soit de type "NSNotification*" ne prouve absolument pas que ça en soit une (c'est juste une simplification de l'API pour utiliser le même objet à  envoyer à  son delegate par callback, et en tant que notification pour tous les autres).
  • psychoh13psychoh13 Mothership Developer Membre
    08:01 modifié #29
    dans 1234113240:

    dans 1234101526:

    Sinon j'insistait surtout sur l'argument NSNotification, pas sur le will. Toutes les méthodes ayant pour argument NSNotification sont des notifications, et comme le délégué est d'office considérer comme "observeur" de la notification, les méthodes de notification sont aussi passées en méthodes déléguées.


    Pas quand elles sont envoyées au delegate justement ! Parce que ça attend le retour, et c'est une différence énorme...
    Par exemple NSWindow va dire à  son "delegate" : "windowWillClose"... Et le delegate va faire tout plein de traitement avant de retourner ; pendant ce temps la fenêtre attendra sagement la réponse.
    Alors que pour les autres, elle va balancer la notification, puis fermer sans se préoccuper de ce qu'ils en pensent.

    Ce n'est pas qu'une relation d'observation, le "delegate" est actif ! (donc même si l'argument est une NSNotification*, ça ne peut être considéré comme une notification dans le sens des notifications Cocoa).


    Faux faux faux et encore faux, tu n'as pas lu tout ce que j'ai dit !

    Pour commencer, les notifications sont envoyés de manière synchrone. Pour que la méthode qui a envoyé la notification puisse continuer son travail, il faut d'abord que toutes les méthodes exécutée par les observeurs aient terminé leur travail.

    Ensuite, toutes les méthodes de notification SONT des notifications, déléguées ou pas ! Lorsque tu donnes ton objet comme délégué d'une fenêtre par exemple, l'objet NSWindow va regarder toutes les méthodes prenant une NSNotification comme argument et va enregistrer ton objet comme observeur de ses notifications. Si bien que si tu fais :
    <br />@implementation MyController<br /><br />- (void)awakeFromNib<br />{<br /> &nbsp; &nbsp;[window setDelegate: self];<br /> &nbsp; &nbsp;[[NSNotificationCenter defaultCenter] removeObserver: self];<br />}<br /><br />- (void)windowWillClose:(NSNotification *)notification<br />{<br /> &nbsp; &nbsp;// Cette méthode ne sera jamais appelée.<br />}<br /><br />@end<br />
    


    La méthode -windowWillClose: ne sera jamais appelée dans ce cas, parce que -setDelegate: aura enregistré self comme observeur de NSWindowWillCloseNotification mais -removeObserver: aura supprimé l'observation.

    Donc, il s'agit bien du comportement normal des notifications, et le fait que ce soit désigné comme méthode déléguée ça indique juste que le délégateur enregistrera son délégué comme observeur de cette notification. Mais si l'observation est supprimée, la méthode n'est plus appelée, délégation ou pas.


    dans 1234112898:

    dans 1234101526:

    Non, non je parle bien des delegates, et c'est écrit dans la documentation : "
    the delegate implements only those methods where it has an interest in coordinating itself with the delegating object or affecting that object's default behavior."



    Tu soulignes que ce qui t'intéresses dans la phrase, et pas ce qui est le plus important  :)
    coordinating itself with the delegating object OR ... "
    Oui, c'est bien la définition d'une callback...
    L'objet qui appelle une méthode déléguée en attend le retour pour recevoir l'information :
    - Soit une réponse qui lui permet effectivement d'affecter son comportement
    - Soit pas de réponse qui lui indique juste que l'objet délégué a bien fini de traiter le message


    Oui, il s'agit de la dérive dont je parle, le fait que le délégué se coordonne avec son délégué, mais à  l'origine c'était surtout pour modifier le comportement de l'objet, d'ailleurs, la plupart des méthodes déléguées (mise à  part les notifications qui n'en sont pas !) modifient le comportement de leur délégateur.

    dans 1234112898:

    Contrairement à  une notification qui est balancée et on passe à  la suite en se fichant de savoir si ça a été bien traité ou pas.


    Donc je répète, les notifications sont envoyées de manière synchrone. Sinon les notifications "NSWindowWillMoveNotification" et "NSWindowDidMoveNotification" n'ont pas de sens... La première intervient avant le déplacement de la fenêtre, et la deuxième après, donc si c'était envoyé de manière asynchrone, tu recevrais la deuxième notification alors que la première n'était pas forcément terminée.
    De plus, si c'était envoyé de manière asynchrone il faudrait une application multithreadée, et jusqu'à  nouvel ordre je ne vois nul part dans la documentation quelque chose disant qu'il faudrait prévoir cette éventualité. C'est-à -dire par exemple qu'il faudrait locker les données, ou s'assurer de leur propreté dans les méthodes appelées par les notifications.

    Conclusion, quand un objet poste une notification, il doit attendre que tous les observeurs aient exécuté leur code pour continuer.

    dans 1234114133:

    Schlum a entièrement raison.
    Le système delegate implanté par les classes cocoa n'est que la traduction "objet" du système des callback utilisés en prog procédurale.

    La différence entre delegate et notification est fondamentale.

    - pour un delegate, l'objet "émetteur", ce dernier interroge s'il a un delegate et s'il implante la bonne méthode. Si oui, il appelle (call) l'objet delegate et attend la fin de l'exécution de la méthode puisque c'est un call. Eventuellement, le delegate peut retourner une valeur (cas par exemple de windowShouldClose de NSWindow) ou modifier l'objet en paramètre (cas de tableView:willDisplayCell:forTableColumn:row: de NSTableView), d'où le terme de callback.

    - pour une notification, l'objet émetteur n'a aucune connaissance du ou DES objets pouvant recevoir les notifs. Pire, la doc Apple indique bien qu'il n'y a aucun synchronisme entre envoi de la notif par l'objet émetteur, et réception par les objets abonnés à  la notification.

    Et c'est normal, car les notifs passe par la boucle d'événement, alors que les delegate ne sont que des appels purs et simples.

    Chaque méthode a donc son avantage :
    - un delagate peut (éventuellement) influancer l'émetteur (puisque appel direct).
    - une notification peut être reçue par une multitude d'objets en même temps.


    Alors là  mon cher No, on ne doit pas lire la même documentation !!!!!!!!!!

    Donc, si vous lisez la partie Overview de NSNotificationCenter vous pourrez lire ceci:

    A notification center delivers notifications to observers synchronously. In other words, the postNotification: methods do not return until all observers have received and processed the notification. To send notifications asynchronously use NSNotificationQueue. In a multithreaded application, notifications are always delivered in the thread in which the notification was posted, which may not be the same thread in which an observer registered itself.


    Ce qui contredit totalement les assertions de Schlum et No comme quoi le notifieur envoie la notification et passe tout de suite à  la suite sans se soucier de l'exécution des notifiés !
  • NoNo Membre
    08:01 modifié #30
    dans 1234115677:

    Alors là  mon cher No, on ne doit pas lire la même documentation !!!!!!!!!!
    Donc, si vous lisez la partie Overview de NSNotificationCenter vous pourrez lire ceci:
    A notification center delivers notifications to observers synchronously. In other words, the postNotification: methods do not return until all observers have received and processed the notification. To send notifications asynchronously use NSNotificationQueue. In a multithreaded application, notifications are always delivered in the thread in which the notification was posted, which may not be the same thread in which an observer registered itself.

    Ce qui contredit totalement les assertions de Schlum et No comme quoi le notifieur envoie la notification et passe tout de suite à  la suite sans se soucier de l'exécution des notifiés !


    Bien vu.
    Effectivement, ce que j'ai dit plus haut n'est plus d'actualité.
    (ce l'était dans de précédentes versions de OSX où j'avais du implanter un système qui suit les mouvements d'une fenêtre, mais le résultat était affreux à  cause de cette non-synchronisation qui était à  l'époque écrite dans la doc).

    A bien relire la doc dont tu as fourni un extrait, je deviens moins affirmatif sur la différence entre delegate et notification.

    Merci Psycho pour cette veille informatique.
  • mpergandmpergand Membre
    08:01 modifié #31
    Grilled par psychoh13   ;)

    dans 1234114396:

    En gros pour être plus clair, quand une NSWindow envoie le message "- (void)windowWillClose:(NSNotification *)notification" à  son delegate, ça ne passe pas par un Notifications Center
    -> ce n'est pas une notification (l'appel est direct et attend le retour).



    Ah bon ???

    windowWillClose:
    Sent by the default notification center immediately before an NSWindow object closes.

    - (void)windowWillClose:(NSNotification *)aNotification

    Discussion
    aNotification is always NSWindowWillCloseNotification. You can retrieve the NSWindow object in question by sending object to aNotification.


    On nous aurait menti  :)

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