J'ai fait cocoa pour la première fois !

itralala

Membre confirmé
16 Octobre 2009
66
1
Bonjour,

J'ai pas pu résister. C'était trop tentant. Bon, je vais rester sérieux pour la suite.
Je présente mon profil : je suis développeur depuis bientôt 20 ans et j'ai décidé de
me mettre au Cocoa pour toucher un peu. Je développe pour l'instant essentiellement
sous des plateformes PC (Windev / php / Visual Basic (pas .net)).

Je viens de me prendre le livre "Programmation Cocoa sous Mac OS X - 3° Edition".

J'ai attaqué ce week end le premier chapitre, un générateur de nombre aléatoires
avec 2 boutons et 1 label (ça sert pour la NSA et le MI6).

Et là, j'ai eu l'impression de tomber de haut. L'interface Builder est très bien, l'éditeur de code est très ergonomique. Mais le niveau de complexité est 55253x plus important que je pensais.

J'ai du coup, 3 ou 4 questions :

- Mes fichiers descripteurs de fenêtre sont des .xib au lieu des .nib décrits dans
le livre --> le livre a beaucoup de retard ?

- Une fois le fichier .xib créé avec les 2 boutons et le libellé, l'auteur fait créer 1 fichier .m et son descripteur .h avec 3 méthodes :

Bloc de code:
#import <Cocoa/Cocoa.h>
@interface Foo : NSObject {
    IBOutlet NSTextField *textField;
}
- (IBAction)initrandom:(id)sender;
- (IBAction)generate:(id)sender;
@end

On a donc (désolé du barbarisme, je ne suis encore pas familiarisé avec les termes) : 1 pointeur en OUT sur une textField et 2 événements.

---> faut-il créer systématiquement et manuellement toutes les méthodes/actions de chaque fenêtre ? (j'avoue avoir pris l'habitude de faire un clic droit sur un objet et d'associer directement le code avec son évènement choisi dans une liste) ??


- J'ai donné un nom explicite à un bouton : btn_InitRandom

Ensuite, je fais pointer le descripteur foo -> initrandom (jusque là, j'ai réussi la manip). Ca me renvoie dans le code du .m :

Bloc de code:
- (IBAction)initrandom:(id)sender
{
    // On se sert de l'heure pour initialiser le randomisateur
    srandom(time(NULL));
    [textField setStringValue:@"Générateur initialisé"];
}


-----> comment faire pour dire en fait que le message s'affiche dans le libellé qui a été renommé en lbl_info ????????




Je suis désolé de ces questions super basiques. J'ai l'impression d'avoir vraiment régressé :(

Merci d'avance,
 
Je viens de me prendre le livre "Programmation Cocoa sous Mac OS X - 3° Edition".
Très bon choix.

Mais le niveau de complexité est 55253x plus important que je pensais.
Oui c'est complexe, mais il ne faut pas avoir peur, quand tu seras à la fin du bouquin, tu connaîtras 70% de ce qu'il faut savoir. Certaines choses (je pense par exemple à l'Undo, ou au copier-coller) sont finalement beaucoup plus simple à coder avec Cocoa.

- Mes fichiers descripteurs de fenêtre sont des .xib au lieu des .nib décrits dans
le livre --> le livre a beaucoup de retard ?
Un peu, il est basé sur Mac OS 10.5.
On peut toujours utiliser les .nib si on veut, mais en pratique, le .xib est un format XML qui est compilé en .nib: regarde le bundle de l'exécutable, il contient bien des .nib, que tu ne peux d'ailleurs pas éditer avec Interface Builder.
Apple a introduit les xib (depuis 10.5) parce que les nib posaient des problèmes avec les logiciels de contrôle de versions.

On a donc (désolé du barbarisme, je ne suis encore pas familiarisé avec les termes) : 1 pointeur en OUT sur une textField et 2 événements.
On a une outlet vers un NSTextField et deux actions…

---> faut-il créer systématiquement et manuellement toutes les méthodes/actions de chaque fenêtre ?
Oui.
Le concept utilisé sous Windows, c'est que le bouton a une méthode Clic, et on crée une sous-classe du bouton pour surcharger cette méthode. Sous Cocoa, le bouton possède une variable d'instance qui est un pointeur vers un objet (sa "cible"). La valeur de ce pointeur est fixée lorsque que nib est désarchivé.
Cocoa préfère toujours la composition au sous-classage. En pratique, c'est peut-être moins facile à comprendre pour un débutant, mais ça décourage de mettre du code "métier" dans le code de l'IHM. Cette séparation de l'IHM et du code métier est fondamentale en Cocoa. C'est ce qu'on appelle le M-V-C. Elle s'avère judicieuse sur tout projet un peu complexe.

- J'ai donné un nom explicite à un bouton : btn_InitRandom
Non, tu as donné un nom à l'action. Par exemple, tu pourrais avoir un article de menu qui déclenche la même action. -initRandom est un meilleur nom.

-----> comment faire pour dire en fait que le message s'affiche dans le libellé qui a été renommé en lbl_info ????????

Comme ça:
Bloc de code:
[lbl_info setStringValue:@"Générateur initialisé"];

Ta question, est plutôt: comment relie-t-on l'outlet lbl_info au NSTextField ? La réponse:
- Sous IB, le xib doit comporter une instance de Foo.
- Tire son outlet lbl_info vers le textField. On fait cela en maintenant le bouton droit de la souris, ou par un Ctrl+Clic.

Franchement, ne cherche pas trop à reproduire ce que tu connais sous Windows; les concepts sont très différents, suis plutôt le livre qui parle de ces sujets en détails.
 
Ca c'est ce que j'appelle une réponse : clair / précis et détaillé.

Je te remercie pour ces informations. Juste en complément :

Envoyé par itralala
- J'ai donné un nom explicite à un bouton : btn_InitRandom

Non, tu as donné un nom à l'action. Par exemple, tu pourrais avoir un article de menu qui déclenche la même action. -initRandom est un meilleur nom.

J'ai pourtant bien mis ça dans Interface Builder Identity / Name. Du coup, faut-il faire suivre le code

Bloc de code:
- (IBAction)initrandom:(id)sender;
- (IBAction)generate:(id)sender;

Donc, et j'en fini avec mes questions :

Dans le .xib, j'ai 2 boutons (btn_InitRandom et btn_Generer) et un libellé (lbl_Nombre)
J'ai rajouté la classe Foo. Le SentAction de btn_InitRandom est lié à initrandom.

Dans le .h, j'ai :
Bloc de code:
#import <Cocoa/Cocoa.h>
@interface Foo : NSObject {
    IBOutlet NSTextField *lbl_Nombre;
}
- (IBAction)initrandom:(id)sender;
- (IBAction)generate:(id)sender;
@end

------> Question, faut-il mettre *lbl_Nombre ? N'y a-t'il pas un moyen d'autocomplétion
de code ?

Dans le .m, j'ai :

Bloc de code:
#import "Foo.h"


@implementation Foo
- (IBAction)initrandom:(id)sender
{
    srandom(time(NULL));
    [lbl_Nombre setStringValue:@"Générateur initialisé"];
}
@end


-------> pareil, faut-il mettre lbl_Nombre manuellement ? Pas d'autocomplétion ?


Et quand je teste, ça affiche rien.......... J'ai donc du bouletter quelque part ::eek::eek::eek:

Je vais aller de ce pas continuer ma lecture et aller sur un site qui me parait intéressant : www.cocoa.fr ;)
 
J'ai pourtant bien mis ça dans Interface Builder Identity / Name. Du coup, faut-il faire suivre le code

Je ne me sers jamais de la liste d'actions et d'outlets sous IB, parce qu'avec les versions précédentes, ça n'a jamais bien fonctionné. En pratique, IB se synchronise automatiquement avec les déclarations tapées sous XCode, alors je tape plutôt les déclarations dans XCode.

Par contre, dans la rubrique Class Name, il faut que tu mettes "Foo"; IB doit savoir quelle classe instancier.


------> Question, faut-il mettre *lbl_Nombre ? N'y a-t'il pas un moyen d'autocomplétion
de code ?
Oui, parce que la méthode qui génère le nombre aléatoire affiche le résultat, et doit donc pouvoir accéder au NSTextField.
Pour l'autocomplétion, appuie sur Esc (ça a un peu changé sur le dernier XCode, jette un &#339;il à la doc + les Préférences).

-------> pareil, faut-il mettre lbl_Nombre manuellement ? Pas d'autocomplétion ?
Oui, il faut le mettre, XCode ne peut pas savoir dans quel textField tu veux écrire (ou alors je n'ai pas compris la question).

Et quand je teste, ça affiche rien.......... J'ai donc du bouletter quelque part
Fais du pas à pas avec le débogueur, tu vas bien voir si tu passes dans les méthodes d'action.
Menu Run > Debug.

Je vais aller de ce pas continuer ma lecture et aller sur un site qui me parait intéressant : www.cocoa.fr ;)
Un autre site intéressant: PommeDev