Créer system event Cocoa
ettibo
Membre
Bonjour à tous,
dans pas mal de classes cocoa, je vois des systèmes d'évents, mais est-il possible de créer des events interclasse, je m'explique.
Dison qu'une classe que l'on va appelé papa contient une classe que l'on va appeler fiston.
Le papa fait sa vie et de temps en temps doit faire effectuer des opérations asyncrhones au fiston.
Le fiston ne sait pas qu'il a un Papa (je dit ça car je voudrais éviter la double inclusion), mais voudrait signaler à tout le monde haut et fort qu'il a fini son boulot.
Et donc le papa doit être en capacité de savoir que son fiston a fini.
Je pens passer par le système de NSNotification.
J'éspère avoir été clair.
Merci d'avance de vos réponses.
dans pas mal de classes cocoa, je vois des systèmes d'évents, mais est-il possible de créer des events interclasse, je m'explique.
Dison qu'une classe que l'on va appelé papa contient une classe que l'on va appeler fiston.
Le papa fait sa vie et de temps en temps doit faire effectuer des opérations asyncrhones au fiston.
Le fiston ne sait pas qu'il a un Papa (je dit ça car je voudrais éviter la double inclusion), mais voudrait signaler à tout le monde haut et fort qu'il a fini son boulot.
Et donc le papa doit être en capacité de savoir que son fiston a fini.
Je pens passer par le système de NSNotification.
J'éspère avoir été clair.
Merci d'avance de vos réponses.
Mots clés:
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Utiliser les NSNotications me semble approprié, oui.
[font=helvetica, arial, sans-serif]L'autre solution serait que le fiston ait un delegate, ce qui permet de lui assigner un objet à qui signaler qu'il a fini. Cet objet tu t'en fiches de qui il est (en l'occurrence ce sera le Papa mais bon) du moment qu'il sait répondre à l'information qd on lui signale.[/font]
[font=helvetica, arial, sans-serif] Et pour la classe Papa : Du coup quand tu crées le Fiston, tu lui affectes l'objet Papa à sa propriété "delegate", et quand le Fiston doit indiquer à son delegate qu'il a fini, il appelle [tt][self.delegate fistonDidFinish:self];[/tt] ce qui va donc appeler cette méthode sur le Papa (en passant le Fiston en paramètre, au cas où, ça peut toujours servir). Avantage : dans toute cette procédure, le Fiston n'a pas besoin de connaà®tre la classe Papa. Pour lui il envoie juste un message à son delegate, quelle que soit la classe de ce delegate. D'où couplage faible.[/font]
[font=helvetica, arial, sans-serif]Bref, cette solution du delegate est un intermédiaire, puisque le Fiston doit avoir un objet à qui signaler qu'il a fini, même si ça reste du couplage faible car il n'a pas besoin de savoir que cet objet est de type Papa.[/font] [font=helvetica, arial, sans-serif]Encore faut-il affecter à un moment donné l'objet de type Papa à son Fiston, même si le Fiston ne sait pas de quel type d'objet il s'agit.[/font]
[font=helvetica, arial, sans-serif]Du coup si tu procèdes ainsi, le Fiston ne va pas "crier haut et fort qu'il a fini à tout le monde", mais "dire à qqun en particulier qu'il a fini, sans se soucier de savoir qui est ce quelqu'un".[/font]
[font=helvetica, arial, sans-serif]Alors que si tu préfères les NSNotifications, qui sont du coup tout aussi bien pour ton cas, le Fiston va crier à tout le monde, et c'est à la charge du Papa d'écouter, de dire que ça l'intéresse, et d'intercepter donc la notification, sans que le Fiston n'en sache rien. Et, autre petite subtilité, plusieurs objets (Papa ou autre) peuvent s'abonner à la notification, là où dans la solution delegate c'est plutôt prévu pour qu'un objet unique soit notifié.[/font]
[font=helvetica, arial, sans-serif]Les deux solutions se valent, il n'y en a pas forcément une meilleure que l'autre (j'ai juste parlé des delegate pour t'indiquer l'existence de cette alternative), après cela dépend de ton besoin, du contexte et de tes préférences d'architecture.[/font]
Sinon, KIXX qu'entends tu par protocole?
Ce n'est pas tout à fait le même mécanisme que les signaux/slots en QT, car en QT tu connectes in signal d'un objet à un slot d'un autre objet, comme si tu avais une ficelle entre l'objet qui émet le signal et le slot qui le reçoit. Et pour ça tu as besoin à un moment donné dans le code d'avoir les deux objets, pour pouvoir écrire [tt]connect(emetteur, SIGNAL(signal), recepteur, SLOT(slot));[/tt]. En ce sens les signaux/slots de QT ressemblent plutôt au mécanisme target/action de Cocoa plutôt.
Alors qu'avec les NSNotification, l'émetteur de la notif et celui ou ceux qui s'y abonnent peuvent ne jamais se voir, et l'émission de la notif peut se faire dans un bout de code totalement séparé de l'abonnement de la notif pour indiquer que tu es intéressé (et bien sûr lui aussi séparé de la réception de la notif quand elle est émise). Tout ça passe par l'intermiédiaire qui est le NSNotificationCenter, ce qui fait que les deux parties peuvent ne jamais être présentes en mm temps dans un même bout de code, chacun vit sa vie séparément.
----
Là où le Design Pattern "delegate" commence à devenir plus intéressant, c'est plutôt si un objet donné a besoin d'être informé du comportement d'un autre à différents stades de sa vie, pour différents événements.
Un exemple typique est une NSURLConnection pour télécharger des données. l'objet NSURLConnection informe son delegate qu'il a trouvé le serveur, démarre la récupération de la réponse, puis qu'il reçoit des morceaux de réponse bout par bout, puis qu'il a fini et a tout reçu... ou bien qu'il y a eu un problème ou une déconnexion, etc... Pour cela, il n'informe qu'un unique objet, à travers le mécanisme de delegate.
Ca ne serait pas très utile qu'il crie cette information sur tous les toits via des NSNotifications alors qu'en général seul l'objet qui se charge de gérer le téléchargement et de manipuler les données reçues est intéressé. Et en plus cela nécessiterai de traiter pas mal de notifications, vu qu'il y a pas mal d'événements différents.
En plus l'avantage d'utiliser un @protocol c'est que les méthodes sont bien définies, avec des noms et des paramètres nommés. Alors qu'une NSNotification passe par un NSDictionary "userInfo" dont il faut connaà®tre les clés. C'est moins "parlant" à la lecture du code.
----
Autre cas où ce Design Pattern est pratique, c'est quand il est nécessaire d'obtenir une réponse. Par exemple si Fiston devait demander à son Papa l'autorisation de faire qqch. Là la NSNotification ne convient pas, car c'est un envoi de message que tu cries sur tout les toits à tout le monde, sans pouvoir recevoir de réponse. Alors que dans le cas du pattern delegate tu peux créer un @protocol dont certaines méthodes vont retourner une valeur et pas "void", et te servir de cette valeur ensuite pour prendre des décisions.
Chose que tu ne peux pas faire avec une NSNotification évidemment que de demander l'avis du paternel /wink.png' class='bbc_emoticon' alt=';)' />
avec le system d'event, mon application crash, quand je fais
j'ai ce message d'erreur:
-[lefils receiveEvent:]: unrecognized selector sent to instance 0x687c9b0
2012-02-06 17:49:29.128 MediActu[2099:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[lefils receiveEvent:]: unrecognized selector sent to instance 0x687c9b0'
Des idees???
Sauf que parmi ceux qui se sont abonnés à cette Notification, tu en as un à qui tu as dit en gros "si tu reçois cette NSNotification, appelle la méthode "receiveEvent:" sur tel objet". Or l'objet en question n'a pas de méthode "receiveEvent:" manifestement, puisque ça plante.
Cas d'école : tu as peut-être une méthode "receiveEvent", sans paramètre, alors qu'il faut implémenter "receiveEvent:" avec les deux-points à la fin donc avec un paramètre. Ce paramètre de cette méthode sera un objet de type NSNotification, contenant la NSNotification envoyée, dont tu pourras récupérer des informations (son nom, son dictionnaire userInfo, ...)
Si c'est le père qui veut s'abonner à la notification que le fils va émettre, pas de soucis.
Il suffit d'écrire pour dire que le père (father) est observeur de la notification nommée kChildDidFinishNotificationName et donc que quand cette notification est émise (par n'importe qui, il s'en fout le père que ce soit le fils qui émette la notif ou un autre), alors appeler la méthode "childDidFinish:" sur l'objet "father" pour le prévenir et traiter la notification.
Encore faut-il que la classe Father implémente dans ce cas la méthode [tt]-(void)childDidFinish:(NSNotification*)notif[/tt] !! Car si ce n'est pas le cas, quand le fils va émettre la notification "kChildDidFinishNotificationName", le NSNotificationCenter va recevoir cette notif et la dispatcher à tous les observeurs intéressés par cette notification (tous les objets abonnés) en appelant le sélecteur associé, donc dans notre cas il va appeler la méthode "childDidFinish:" sur l'objet "father", et si cette méthode n'existe pas, appeler une méthode qui n'existe pas sur un objet provoque l'exception que tu as eue.
Je te conseille la lecture du Notification[url="https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Notifications/Introduction/introNotifications.html#//apple_ref/doc/uid/10000043i]Notification"] Programming Guide[/url] pour plus d'infos, comme pour tous les Programming Guides d'Apple il est très complet et explique tous les principes en détail, avec exemples à la clé.
Quel code utilises-tu pour abonner le père à la notification ? Tu peux nous mettre ici les extraits de code que tu as écrit tant pour le père que pour le fils ?
et en relisant ton code, je crois que je viens de comprendre, il faut que je change
addObserver:self.lefils par addObserver:self
et oui, c'était bien ça.
Merci
D'ailleurs, pour rappel, le père n'observe pas le fils ! Le père n'a pas à avoir connaissance du fils.
- Le père observe une notification @DidFinishDownload c'est tout. quel que soit celui qui va émettre cette notification.
- Le fils va émettre la notification et la crier sur tous les toits (enfin va le crier au NotificationCenter en fait.
- Mais le père et le fils ne sont pas liés directement, dans ce process. C'est même le principe du pattern utilisé dans les Notifications, l'un crie haut et fort un message à qui veut l'entendre, et ensuite ceux qui sont intéressés en font ce qu'ils veulent, celui qui a crié le message s'en fout de qui l'a entendu, ce ceux qui l'ont entendu se foutent de connaà®tre celui qui a crié.
Le NSNotificationCenter qui sert d'intermédiaire permet de faire la séparation, de recevoir toutes les notification émises d'un côté, de les redistribuer à qui est intéressés de l'autre, mais chaque partie de part et d'autre n'a pas à se connaà®tre.
tu as l'air de bien connaitre que ce soit le c++ dont QT et l'objective C à la fois, comment fais tu cet exploit?
ça s'appelle l'expérience...jeune Padawan...
Au final j'ai vu des langages et des frameworks, de C, C++, C#, Objective-C et leurs libs/fmk respectifs stdlib, .QT, NET, Cocoa... sans parler des langages de scripting (AS, javascript, python, PHP) et j'en passe, la liste est longue.
Mais il n'y a pas grand chose d'exceptionnel là dedans, ceux ici qui ont autant d'expérience que moi ont aussi vu pas mal de langages dans leur carrière ; le propre d'un bon ingénieur est de savoir apprendre de nouvelles technos, et passer d'un langage à l'autre n'est pas un problème quand tu es habitué. Ce ne sont que des outils au final.
Mais encore une fois, va lire le Programming Guide associé (en plus bien sûr de la Class Reference) tout y est expliqué /wink.png' class='bbc_emoticon' alt=';)' />
Et tu as bien sûr aussi la "DevPedia" Apple qui t'explique le principe général également
le sender:
- (void)sendNotif{
NSNotification *tmp = [NSNotification notificationWithName:@validateButton object:nil];
[tmp setValue:myUsername.text forKey:@user];
[tmp setValue:myPass.text forKey:@pass];
[[NSNotificationCenter defaultCenter] postNotification:tmp];
}
le receiver:
- (void)sendLoginInformations:(NSNotification *)notification
{
NSLog(@Username: %@, Pass: %@", [notification valueForKey:@user], [notification valueForKey:@pass]);
}
mais ça n'apprécie pas le setValue /sad.png' class='bbc_emoticon' alt=':(' />
Je vois pas ce qu'il y a de compliqué, en plus le code est plus simple que ton pseudo-code (moins de lignes)