où placer les méthodes associées à une action (toujours sans IB)
bofy
Membre
Bonjour
Je sais associer une action à un menuitem, par exemple ouvrir une fenêtre avec des boutons et des textfields. Je fais à peu près ce que je veux.
Mais une première chose me chagrine : je dois mettre dans un delegate de NSApp les méthodes associées à mes menuitem ?
La deuxième : je voudrais que un bouton de ma fenêtre grise le menuitem d'appel si une condition est YES ; pour cela il me semble que les notifications sont bienvenues ; or impossible de récupérer la méthode indiquée par le selector dans le addObserver !
Je n'ai pas vraiment compris la logique qui permet d'associer une action à un objet et plus précisément où placer la méthode correspondante ? Faut-il nécessairement placer cette méthode dans un delegate de cet objet ? Quid en ce qui concerne les notifications ?
SVP, ce n'est pas la peine de répondre si c'est pour dire YAKA lire la doc sans autre précision
Je sais associer une action à un menuitem, par exemple ouvrir une fenêtre avec des boutons et des textfields. Je fais à peu près ce que je veux.
Mais une première chose me chagrine : je dois mettre dans un delegate de NSApp les méthodes associées à mes menuitem ?
La deuxième : je voudrais que un bouton de ma fenêtre grise le menuitem d'appel si une condition est YES ; pour cela il me semble que les notifications sont bienvenues ; or impossible de récupérer la méthode indiquée par le selector dans le addObserver !
Je n'ai pas vraiment compris la logique qui permet d'associer une action à un objet et plus précisément où placer la méthode correspondante ? Faut-il nécessairement placer cette méthode dans un delegate de cet objet ? Quid en ce qui concerne les notifications ?
SVP, ce n'est pas la peine de répondre si c'est pour dire YAKA lire la doc sans autre précision
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
N'importe quel objet peux implémenter la méthode.
Après que l'utilisateur ait cliqué sur le menuItem, cet item exécute une suite d'instructions qui en simplifié doit être à peu près cela :
id target = [self target];
 SEL selector=[self selector];
 [target performSelector:selector withObject:self];
Cela a pour effet d'envoyer directement le message d'exécution à target, la méthode étant précisée par le selector et l'argument étant sender=self.
On voit bien que cela peut se faire pour n'importe quel target, sans intervention du mécanisme des notifications.
Le NSButton réagit au clic de la même façon que le NSMenuItem.
 id target = [self target];
 SEL selector=[self selector];
 [target performSelector:selector withObject:self];
Tous les deux doivent avoir été renseignés sur leur target et selector.
Par exemple considérons un objet quelconque qui a une référence sur myButton et sur le menuItem
Dans la phase d'initialisation, et lorsqu'on sait que myButton a été alloc/init-isé
 [myButton setTarget:self];
 [myButton setSelector:@selector(toggleMenuItem];
et quelque part dans le code de la classe de cet objet
-(void) toggleMenuItem:(id)sender {
  if([myMenuItem isEnabled]) {
    [myMenuItem setEnabled:NO];
  } else {
    [myMenuItem setEnabled:YES];
  }
}
C'est un simple envoi de message. Il faut que l'objet ait connaissance de l'objet cible (target) à qui envoyer le message, et d'une référence (selector) de la méthode a exécuter que possède cet objet cible
Cela peut-être de manière plus élégante encapsulé dans une NSInvocation
NSMethodSignature * methodSignature=[self methodSignatureForSelector:@selector(rightClic];
NSInvocation * invocation=[NSInvocation invocationWithMethodSignature:methodSignature];
[invocation setTarget:....];
    [invocation setSelector:@selector( .... )];
Les notifications suivent un mécanisme indirect :
• L'objet qui veut répondre à une invocation s'inscrit dans un centre de notifications
• Le bouton, le menuItem, ou n'importe quoi poste une notification et l'envoie au centre de notifications
• Le centre de notifications redistribue le message à qui le veut.
Le KeyValueObserving est une troisième méthode d'envoi de transmissions de message, qui semble inappropriée ici.Â
Cela veut-il dire qu'il faut créer une classe pour tout objet pour lequel on veut utiliser un selector ? Autrement dit sous-classer une classe cocoa pour pouvoir y insérer le code de la méthode associée ?
Je vais essayer tout ça en détail, notamment le NSInvocation dont je ne vois pas vraiment l'utilité, pour l'instant...
J'ai essayé plein de trucs, dont sous classer les menuitem (les delegate semblent ne pas marcher sur cette classe), mais le selector de l'action n'est pas reconnu.
La seule chose qui marche est de créer un delegate de NSApp et d'y placer les méthodes-action des menuitem !!!...
Je n'ai toujours rien compris : du code SVP
(c'est bien de dire
mais où je le mets ?
ne marche pas ...
Merci
Je pense que tu as créé une classe qui contient toutes les méthodes (les actions) que tes menuitems vont lancer.
Je pense que tu as instancié cette classe pour obtenir un objet.
Donc, il ne te reste plus qu'à mettre le pointeur de cet objet dans target, et le selector (obtenu par @selector(uneMethode pour déclencher la méthode uneMethode: par exemple) dans selector.
C'est simple comme bonjour.
Note, je crois que la signature de la méthode action doit toujours être de la forme - (void)uneMethode:(id)sender.
Je pense que les noms parlent par eux-même
sachant que la méthode-action est dans ConnConnMenuItemCtrl :
Je ne comprends pas pourquoi ça marche lorsque je place cette méthode dans le delegate de NSApp?...
[connConnMenuItem setTarget: self];
dont la classe implémente la méthode
-(void)connConnAction:(id) sender ou -(IBAction)connConnAction:(id) sender
Et comme disent les bègues, c'est connConnContrôlé ::)
La méthode de la classe NSMenuItem :
- (id)initWithTitle:(NSString *)itemName action:(SEL)anAction keyEquivalent:(NSString *)charCode
ne définit pas la cible target.
Si target=nil
Un mécanisme spécial est alors prévu : Le message correspondant est envoyé à la chaà®ne des responder de l'application. Cette chaà®ne , "automatiquement" mise en place au lancement de l'application, se termine, sauf intervention explicite du programme par la mainWindow (ou son delegate), et l'instance de l'application ( ou son delegate).
Ainsi, logiquement, ton message après avoir été refusé par la mainWindow, a été tranmis au delegate de NSApp. Ton NSApp-delegate ayant une méthode adéquate a pu y répondre.
T'as bien embrouillé l'esprit de Boffy avec le performSelector:withObject:, les bindings, les NSInvocation, et, pire, les setTarget:self (ce qui est d'ailleurs presque une hérésie en cocoa) dans tes précédents messages.
Reste simple.
si ta classe ConnConnMenuItemCtrl est une sous classe de NSMenuItem, alors je crois que tu vas droit dans le mur du MVC si jamais tu codes ta méthode d'action au sein de ton item.
Ben répondre aux questions posées, cela me semble le minimum.
Bofy semble vouloir démonter la machine en faisant sans IB, on lui démonte, cela répond à son questionnement ... Bofy prenant le problème à l'envers (sans la partie masquée de IB) les réponses ne peuvent pas être simples. Il me semble que ce qu'il veut c'est voir comment ça marche, pas vraiment le faire marcher.
Le plus drôle dans l'histoire, ici, c'est que ce serait très acceptable que le NSApp-delegate réponde ici au menu, comme cela a été "obtenu par hasard". Si toutefois Bofy ne nous a pas fait la blague ::) de déclarer le menuitem ... comme NSApp-delegate ce qui serait là une offense à l'académisme officiel en cours.
Â
En plus ça marche, semble-t-il, parfaitement, cf. réponse à Philippe.
En tout cas, en ajoutant :
après le
ça semble parfaitement marcher, et c'est logique quand on a compris que le initWithTitle ne définit pas implicitement la target...
A la fin du paragraphe cité ci-après, je rajouterais : "le faire marcher dans un but de production industrielle, certes non, mais avoir un logiciel Cocoa créé par moi sur Mac et qui marche avec PostgreSQL (ce qui n'est pas le plus difficile), certes oui.
Pour finir, une fois encore, MERCI A TOUS.
C'est un mur dans le sens où c'est la stratégie classique actuelle, recommandée, pour organiser l'interaction des instances que l'on crée dans ce genre de langage.
Voici [url=http://fr.wikipedia.org/wiki/Modèle-Vue-Contrôleur]un article de Wikipedia sur le sujet[/url]
Je profite de ce passage pour vous demander si vous utilisez un framework PostgreSQL (si oui, où puis-je le trouver ?) ou si vous utilisez directement les libs C clientes de PGSQL ?
D'avance merci.
http://sourceforge.net/projects/pgsqlcocoa/
L'intérêt est la simplicité : une classe pour la connection, deux classes pour accéder à PGSQL. De plus c'est totalement indépendant de l'installation de PostgreSQL. Bien sûr, ça ne fait pas tout, mais c'est suffisant pour ce que je veux faire.
J'en ai fait un framework qui marche bien, semble-t-il, mais dont je ne garantirais pas la robustesse.
Je peux t'envoyer le source et/ou même mon framework, si tu m'envoies un message pour que j'aie ton adresse mail.
J'avais regardé le framework cité par@ Schlum : il m'avait semblé bien compliqué pour ce que je voulais faire, mais bien sûr il est certainement plus robuste, sinon stable.
En outre, il y a pgAdmin3 pour l'administration complète des bases pgsql
http://www.pgadmin.org/