Quel livre pour apprendre cocoa ?

Première réponse :

Losrque t'as créé ton interface, pour la zone de saisie tu as 'drag'n dropper' l'element textView de la palette de IB.
les deux champs nombre de mot et dernier mot sont des NSCell.

Pour le codage de ton Controllet :
Première chose à savoir c'est que ton controller 'controle' ton interface. La première chose c'est que dès que ton interface s'affiche, le nombre de mot est de 0 et le dernier mot à blanc. Pour initialiser tes zones tu dois utiliser la methode awakeFromNib. cette méthode est TOUJOURS appelée par le runtime cocoa avant que l'interface soit affichée.
Dans cette methode tu mettras donc

[afficheNbWord setIntValue:0];
[afficheLastWord setStringValue:mad:" "];

Ce sont 2 methodes de l'objet NSCell dans la rubrique 'Setting' and getting cell values' de la doc de Application Kit.

Ensuite ton objet zoneDeSaisie est un NSTextView. Or en consultant la doc de cet objet dans Application Kit, on s'apperçoit que cet objet herite de NSText. Donc toutes les methodes de NSText s'appliquent.
Deuxième chose, il faut voir la zone de saisie comme du texte en continu donc une longue NSString . Donc pour transformer en NSString on consulte les methodes de l'objet NSText et Ô miracle la methode string le fait.
NSString leTextte = [zoneDeSaisie string];
On peut alors considérer qu'une chaine de caractères est un ensemble de mots separés par des blancs.
Or dans la rubrique dividing stings de l'objet NSString (Fondation Kit), j'ai la méthode componentsSeparatedByString qui permet de diviser une chaine en un ensemble (NSArray.

donc ensembleDeMots = [leTexte componentsSeparatedByString:mad:" "] ou simplement
ensembleDeMots = [[zoneDeSaisie string] componentsSeparatedByString:mad:" "];

Le tour est joué. En effet avec un objet NSArray la methode count me donne le nombre de mots et la methode lastObject me donne le dernier mot.

[afficherLastWord setStringValue:[ensembleDeMots lastObject]];
[afficherNbMots setIntValue:[ensembleDeMots count]];

Il reste une question ou mettre toutes ces instructions?
C'est là où on fait appel à la puissance de Cocoa et de l'objet NSText.
Une chose importante quand tu lis la doc d'une classe Cocoa Objective C, il y a 4 zones importantes.
la zone Adopted Protocols qui regroupe la liste des 'protocoles' auquels la classe se conforme (j'expliquera cela après), la zone des méthodes de la classe, puis la zone Delegate Method types qui est la liste des méthodes appelés par l'objet à des moments précis.
Enfin la zone Notifications qui regroupe l'ensemble des méthodes envoyés par un objet au NotificationCenter pour informer les autres objets du changement de son état. Ces méthodes sont à déclarer par un objet qui doit être déclaré comme délégué d'un objet NSText ou NSTextView.
Donc dans la methode awakeFromNib de counter en plus des 2 methodes d'initialisation décrites plus haut je dois ajouter : [zoneDeSaisie setDelegate:self]; ton objet Counter est le délégé du NSTextView zoneDeSaisie.
la methode du délégué qui m'interesse est textDidChange. Cette methode du délégué est appelée à chaque fois que tu tapes le texte.
En résumé : Counter contient deux methodes
- awakeFromNib pour l'initialisation
- textDidChange pour afficher tes champs à chaque modification de ton texte saisi.
Je t'ai montré comment utiliser la doc Cocoa, puis je t'ai sensibilisé à la notion d délégué qui est en Cocoa hyper importante et qui justement fait de Cocoa quelque chose de très fort.
J'expliquerai plustard les notions de délégué et de Notification si tu veux bien.
 
Merci de prendre le temps d'écrire des posts si longs... :)

Pour la première application qui compte les lettres d'une phrase, elle marche. J'ai voulu ajouter ça pour le pluriel possible au mot lettre :

<font class="small">Code:</font><hr /><pre>
if (nb_lettres &gt; 1) {
NSString *mot_lettre=@"lettres";
}
else {
NSString *mot_lettre=@"lettre";
}
</pre><hr />

Mais je me prends des warnings sur mot_lettre. Pourtant dans la doc project omega, c'est de cette façon qu'on déclare une phrase il me semble !

Pour awakeFromNib, j'ai compris à quoi ça servait, mais là je ne vois pas à quoi ça servirait d'initialiser les variables au lancement de l'appli. Quel en est le but exact ? ça marche sans (dans mon cas), p-e que c'ets super utile pour d'autres applis certes...

Maintenant, je vais m'attaquer à la deuxième appli, celle qui compte les mots et affiche le dernier mot.

up.gif
 
C'est une bonne habitude qu'il faut prendre qu'on on fait du Cocoa. En plus c'est logique car ta zone de saisie étant vide ton compteur doit afficher 0 et non être à blanc. Moi pour chaque Controller j'ai toujours un awakeFromNib même vide.
D'autre part un NSString est un objet pas une variable. Ton affectation ne lui plait pas.

NSString *toto =[NSString stringWithString:mad:"texte"] est plus appropeié.
 
OK, compris. :)
C'est vrai que j'avais mis ??? à la place, mais un champ vide est mieux.

Quid du pb pour le NSString ?
 


Quid du pb pour le NSString ?

[/QUOTE]

NSString est une classe NSString *toto déclare un objet. Tu ne peux faire une affectation NSString *toto = xxxx;
il faut utiliser une methode d'affectation. Par exemple stringWithString, etc.
 
Je comprends pas.

Dans le tutorial 7 de cocoa POmega, il est écrit :

"
Objective-C nous fournit une grande syntaxe pour créer ces chaînes :

NSString *aString = @"hello again";
"


NSString pointe vers l'objet aString.

Moi, çe ne marche pas parce que l'objet n'est pas créé ???
 
Manu a dit:
NSString est une classe NSString *toto déclare un objet. Tu ne peux faire une affectation NSString *toto = xxxx;
il faut utiliser une methode d'affectation. Par exemple stringWithString, etc.
Ben non.
siffle.gif

Tu as le droit de faire: NSString *toto = @"toto";
Cela crée un objet NSString constant à la compilation et est équivalent à :
NSString *toto = (NSString *) CFSTR("toto");

<blockquote><font class="small"> izostar:</font><hr />
if (nb_lettres &gt; 1) {
NSString * mot_lettre =@"lettres";
}
else {
NSString *mot_lettre=@"lettre";
}

Mais je me prends des warnings sur mot_lettre. Pourtant dans la doc project omega, c'est de cette façon qu'on déclare une phrase il me semble !

[/QUOTE]
Le problème vient sûrement du fait que tu déclares dans chaque boucle une variable 'mot_lettre' différente...

Fait plutôt comme ça:
NSString * mot_lettre = nil;
if (nb_lettres &gt; 1) mot_lettre =@"lettres";
else mot_lettre=@"lettre";

Ou encore plus court: NSString * mot_lettre = (nb_lettres &gt; 1) ? @"lettres" : @"lettre";

A+
wink.gif
 
Mea Culpa en effet j'en suis encore au vieu NeXTSTEP. Faisant plus du Java J2EE j'ai quelque peu oublier les évol de Cocoa.
 
la tortue a dit:
Le problème vient sûrement du fait que tu déclares dans chaque boucle une variable 'mot_lettre' différente...

Fait plutôt comme ça:
NSString * mot_lettre = nil;
if (nb_lettres &gt; 1) mot_lettre =@"lettres";
else mot_lettre=@"lettre";

Ou encore plus court: NSString * mot_lettre = (nb_lettres &gt; 1) ? @"lettres" : @"lettre";

A+
wink.gif

Diable, tout cela marche en effet.
Joie. Merci la tortue.
 
Manu, j'ai essayé de faire ton appli.

J'ai presque fini, mais je n'arrive pas à m'en sortir avec textDidChange...
J'ai du mal à comprendre le principe manu. Cette méthode surveille si on tape du texte au fur et à mesure mais je ne sais pas comment l'appeler.

D'autre part, je ne pige pas pourquoi on pourrait pas faire un setStringValue à un NSTextView... d'après ce que me dit un warning dans le awakeFromNib.
 
Ah, ça y est, ça marche !

countwords.gif


Je mets le code, il y a peut-être des choses qui marchent mais qui ne sont pas logiques :

countwords_code.gif


En fait, j'ai pas bien pigé l'histoire du setDelegate:self
On informe que l'objet à surveiller en permanence est texteSaisi ?
Et à quoi sert le self ? C'ets pour dire qu'il se trouve dans cette classe ?
 
En fait, j'ai pas bien pigé l'histoire du setDelegate:self
On informe que l'objet à surveiller en permanence est texteSaisi ?
Et à quoi sert le self ? C'ets pour dire qu'il se trouve dans cette classe ?

[/QUOTE]

Saches que ton Controleur que tu as crée dans IB est un objet derivé de NSObject. Il est représenté dans IB sous la forme d'une brique quand tu l'instancie.
Pour bien piger Cocoa il faut comprendre le principe de délégation et celui de Notification.
Un objet de type View est un élément d'interface donc à tout moment son aspet peut changer. Ce changement peut influencer celui des autres éléments c'est à dire d'autres objets. c'est pour cela que beaucoup d'objets de Application kit ont des méthodes dites de délégué. Ces méthodes ont un nom connu comme textDidChange. A chaque fois que tu modifies le texte, la méthode textDidChange est exécutée. On dit en objet que l'objet textView envoie le message textDidChange à son délégué. ton textesais c'est ton objet textView et le [texteSaisi setDelegate:self] codé dans l'objet Controleur dit en fait que moi Counter (self) je suis l'objet délégué de texteSaisi. Donc à chaque fois que texteSaisi est modifié, en temps réel la méthode textDidchange de son délégué est exécuté.
On objet on dit que l'objet NSTextView quand il change, envoie à son délégué le message textDidChange.
Tu remrqueras une chose curieuse, a aucun moment tu n'appelles une de des méthodes de Controleur.
 
izostar a dit:
D'autre part, je ne pige pas pourquoi on pourrait pas faire un setStringValue à un NSTextView... d'après ce que me dit un warning dans le awakeFromNib.

setStringValue n'est pas une méthode de NSTextView ni d'une des classes dont il hérite. (NSText,etc)
 
Oui, c'est ce que je me disais, mais je trouve pas cela logique. :) On y entre du texte aussi... (mais je vais pas remttre en cause la conception des classes, j'ai que 5 jours de cocoa...).
sick.gif
 
Manu
Quel intérêt (s'il y en a un) de coder [textsaisi setDelegate: self] plutôt que de passer par IB ?
 
izostar a dit:
Oui, c'est ce que je me disais, mais je trouve pas cela logique. :) On y entre du texte aussi... (mais je vais pas remttre en cause la conception des classes, j'ai que 5 jours de cocoa...).
sick.gif

NSTextView n'est pas un NSControl et setStringValue est une méthode de NSControl.

NSTextView possède les méthodes string et setString (en fait de NSText)
 
En pratique, avec ma petite expérience, j'utilise NSTextView uniquement pour faire du "traitement de texte". Dans la plupart des cas, NSTextField est plus pratique, s'il ne s'agit que de partager une information avec le controleur. Mais il ne supporte pas, par exemple, les sauts à la ligne.

Pour être encore plus clair, je suis en train de taper un message dans un TextView ; alors que "Re: Quel livre pour apprendre cocoa ?" se trouve dans un TextField.
 
Tiff a dit:
Manu
Quel intérêt (s'il y en a un) de coder [textsaisi setDelegate: self] plutôt que de passer par IB ?

En fait je l'ai fait faire comme cela uniquement pour une raison pédagogique. pour pouvoir expliquer la notion de délégué. En effet sous IB on peut le faire. L'autre avantage d'après moi c'est que lors d'une maintenance de l'appli, on s'attache plus au code qu'aux connections réalisées sur IB qu'on peut facilement oubliées.
En général j'utilise IB pour définir les outlets et actions. Mais avec le système des Bindings apportées par la version cocoa de Panther on fera beaucoup plus de choses sur IB pour diminuer sensiblement le fameux 'glue code' du Controller. Il faut noter que l'utilisation des bindings n'est pas nouvelle en effet elle est faite dans WebObjects depuis longtemps. C'est d'ailleurs ce qui fait sa force.
 
mpergand a dit:
NSTextView n'est pas un NSControl et setStringValue est une méthode de NSControl.

NSTextView possèdent les méthodes string et setString (en fait de NSText)

OK, ok, j'ai compris maintenant. :)
 
Tiff a dit:
En pratique, avec ma petite expérience, j'utilise NSTextView uniquement pour faire du "traitement de texte". Dans la plupart des cas, NSTextField est plus pratique, s'il ne s'agit que de partager une information avec le controleur. Mais il ne supporte pas, par exemple, les sauts à la ligne.

Pour être encore plus clair, je suis en train de taper un message dans un TextView ; alors que "Re: Quel livre pour apprendre cocoa ?" se trouve dans un TextField.

Attention, ce n'est pas tout à fait juste.
NSTextView sert principalement à éditer du texte stylé (NSAttributedString) avec une mise en page pouvant être complexe.

En revanche NSTextField est un NSControl avec une seule cellule NSTextFieldCell, qui utilise à son tour un NSTextView pour l'édition du texte qu'elle contient, quand le NSTextField devient "firstResponder" dans sa fenêtre. Ce NSTextView est souvent le même pour tous les petits bouts de texte par ci par là. C'est en réalité l'objet NSText qui est "fieldEditor" pour la fenêtre.
Le fonctionnement des NSTextField paraît plus simple que les NSTextView, mais c'est faux.
wink.gif


NSTextField comme tous les principaux NSControl sert à éditer une "valeur" ici une chaîne de texte.

A+