# Questions sur Cocoa



## simon (30 Juin 2004)

Hello tout le monde,

Je suis pas un spécialiste de cocoa, mais vu que je suis en vacances je veux en apprendre un peu peu plus 

Après avoir fait les tutorials livré avec XCode ainsi que la lecture du livre de  Aaron Hillegass, je me suis décidé à faire ma petite app cocoa. Le but est assez simple, je trouve le système de playlist très pratique et je voulais en implémenter un, j'ai donc pris un tableview et à côté plusieurs textfield qui contiennent certaines infos. J'ai réussi grâce à l'aide d'un bouton à rajouter des entrées dans le tableview sans problème et également initialiser les textfields avec des valeurs par défaut. J'ai également implémenter une notification pour gérer le changement de sélection dans le tableview. Pas de problème  maintenant je voudrais pouvoir modifier le contenu des textfield et garder ses modifications. c'est là que j'ai un problème parce que je sais pas trop comment mi prendre je ne veux pas mettre un bouton save je voudrais que les modifs se fassent toutes seules (c-à-d que l'utlisateur modifie les textfields mais pas besoin de sauver ou de valider). J'ai pensé utiliser des notifications sur les textfields mais je m'en sors pas parce que j'ai quand même une dizaine de textfield, l'autre solutions serait de faire une méthode updateValue qui est appellé lorsque l'utilisateur sélectionne une autre entrée dans la table. Vous en pensez quoi ? merci d'avance d'éclairer mes lanternes


----------



## mpergand (30 Juin 2004)

Tu as les méthodes textDidEndEditing ou textDidChange (ou controlTextDidChange de NSControl) qui devraient t'aider. Mais je ne comprends pas vraiment pourquoi tu ne fais pas l'édition directement dans le tableView ?


----------



## la tortue (30 Juin 2004)

Selon le sytème MVC, les textfields ne doivent pas contenir les données, mais uniquement les afficher.
Donc, il te faudrait autant de variables NSString dans ton controller que tu as de textfields. Et quand un textfield est modifié (soit par notification, soit directement par target/action), tu mets à jour la ou les variables correspondantes et tu actualise l'affichage (textfields + tableview). 

A+


----------



## Anonyme (1 Juillet 2004)

Je ferai comme mpergand, il est plus facile d'éditer les modifications directement dans la tableView, avec une méthode, plutôt que de repasser par les textFields :


```
- (void)tableView:(NSTableView *)aTableView
        setObjectValue:(id)anObject
        forTableColumn:(NSTableColumn *)aTableColumn
        row:(int)rowIndex
{
//ton code
}
```

Pour la sauvegarde automatique, tu peux faire une méthode par exemple :


```
- (void)saveData
{
    [ton_tableau writeToFile:fichier_de_sauvegarde atomically:YES];
}
```

et l'appeler où tu en as besoin à chaque méthode où tu modifies tes données.

et tu peux enregistrer ds un fichier de prefs par exemple :


```
sitesFile = [NSString stringWithString:@"~/Library/Preferences/tonProg.plist"];
sitesFile = [sitesFile stringByExpandingTildeInPath];
[sitesFile retain];
```

Tu déclares ça ds ton awakeFromNib.

Voilà, je suis débutant, j'espère que je dis pas trop de conneries.


----------



## simon (1 Juillet 2004)

Merci de vos réponses, pour la proposition de tout passer par un tableView je veux bien mais je vois pas comment. Je vous met un screen shot pour que l'on se comprenne bien 

Le but est que quand on sélectionne un Game dans le tableview les textfields de l'aute côté se mettent à jour tout seul. Dans mon application j'ai une classe Game qui contient les infos (nom, parcours, date,....). Lorsque que l'on clique sur le + (en bas du tableview) on initialise un nouvel object avec des valeurs pas défaut 

Merci


----------



## mpergand (1 Juillet 2004)

La soluce de ton problème est de créer une classe contrôleur qui sera déléguée de NSTableView (méthode setDelegate). Regarde dans la doc les méthodes déléguées de NSTableView, tu devrais y trouver ton bonheur (ex: tableViewSelectionDidChange) Cette classe controleur devra posséder un outlet de tous les texfields que tu désires mettre à jour lorsque tu recevras la notification de changement de sélection dans NSTableView. Même principe pour les boutons +/- , définir, dans ce même contrôleur, les action, delegate, outlet, etc, qui te seront nécessaire 

[edit]

Comme tu as pas mal de textField, créer un outlet pour chaque est un peu pénible, dans ce cas il est possible d'utiliser les tags dans InterfaceBuilder, et dans ton code tu utilises la méthode viewWithTag de NSView, pour les récupérer.


----------



## simon (1 Juillet 2004)

mpergand a dit:
			
		

> La soluce de ton problème est de créer une classe contrôleur qui sera déléguée de NSTableView (méthode setDelegate). Regarde dans la doc les méthodes déléguées de NSTableView, tu devrais y trouver ton bonheur (ex: tableViewSelectionDidChange) Cette classe controleur devra posséder un outlet de tous les texfields que tu désires mettre à jour lorsque tu recevras la notification de changement de sélection dans NSTableView. Même principe pour les boutons +/- , définir, dans ce même contrôleur, les action, delegate, outlet, etc, qui te seront nécessaire
> 
> [edit]
> 
> Comme tu as pas mal de textField, créer un outlet pour chaque est un peu pénible, dans ce cas il est possible d'utiliser les tags dans InterfaceBuilder, et dans ton code tu utilises la méthode viewWithTag de NSView, pour les récupérer.



Merci, cela me rassure c'est exactement ce que j'étais entrain de faire   je vous tiens au courant de la chose


----------



## simon (3 Juillet 2004)

J'ai un peu modifier mon interfac, pour l'instant tout fonctionne mais j'ai encore une petite question. Comment puis-je faire pour modifier la couleur du text dans une cellule précise de ma NSTableView ? merci


----------



## mpergand (4 Juillet 2004)

Il faut utiliser NSAttributedString initWithString:attributes
avec pour attributes un NSDictionary dictionaryWithObject: NSColor forKey: NSForeGroundColorAttributeName


----------



## la tortue (5 Juillet 2004)

Il faut que le delegate de ta NSTableView implémente la méthode:

```
- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell
forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
```
Dedans tu peux modifier l'aspect de la cellule avec [aCell setTextColor:[NSColor etc]];

A+


----------



## Manu (5 Juillet 2004)

Une info en passant. Quand on a des textfields comme les tiens, il est plus facile de les gérer en utilisant une matrice de textfields. Il est donc  plus facile de faire des associations d'éléments de la tableview aux élélments d'une matrice en utilisant un même index par exemple.


----------



## simon (5 Juillet 2004)

Merci pour toutes ses informations. En fait j'ai un peu modifier la chose et l'interface. J'utilise maintenant 3 NSTableView (une pour les parties, une pour les trous et une pou les players). Tout fonctionne bien pour l'instant et je dois dire que le Cocoa n'est pas forcément très compliqué mais j'ai un peu de peine encore à utiliser l'API de manière optimale  mais vu que j'obtiens plein de réponse très pratique grâce à vous


----------



## simon (6 Juillet 2004)

Voici ce que cela donne pour l'instant  dites moi ce que vous en pensez, pour l'instant on ne peut pas sauver  mais j'y travail


----------



## molgow (6 Juillet 2004)

Ca quitte au lancement. As-tu pensé à compiler en mode deploy ?


----------



## simon (6 Juillet 2004)

molgow a dit:
			
		

> Ca quitte au lancement. As-tu pensé à compiler en mode deploy ?



 non parce que sincèrement je connais pas trop ton mode deploy   (arfff le Java c'est quand même mieux   mais non je rigole c'est juste parce que je connais mieux le Java et non je ne veux pas relancer l'éternel combat entre Java et Cocoa)

Et pis pendant que j'y suis comment je fais pour sauver mon document. J'ai implémenté:


```
- (void)encodeWithCoder:(NSCoder *)coder;
- (id)initWithCoder:(NSCoder *)coder;
```

Dans la classe de l'objet que je veux sauver, et dans mon controlleur j'ai implémenté:
	
	



```
- (NSData *)dataRepresentationOfType:(NSString *)aType;
- (BOOL)loadDataRepresentation:(NSData *)data ofType:(NSString *)aType {
```

mais quand je vais dans le menu File -> Save rien ne se passe  :hein: je précise que mon app n'est pas une application basé sur NSDocument

Merci encore d'avance  et bon app


----------



## mpergand (6 Juillet 2004)

C'est du Java 

Pour sauvegarder, dans dataRepresentation :

NSData data=NSKeydArchiver.archivedDataWithRootObject(myClass);

et pour recharger, dans loadDataRepresentation:

myClass=(MyClass)NSKeyedUArchiver.uarchiveObjectWithData(data)


J'utilise NSKeyedArchiver, car j'ai eu des problèmes avec NSArchiver.

[edit]

J'avais pas vu !


> mais quand je vais dans le menu File -> Save rien ne se passe  je précise que mon app n'est pas une application basé sur NSDocument


Ben oui, normal que ça marche pas  


Tout d'abord, créer un objet delegate de NSApplication et implémenter applicationOpenFile

Pour la sauvegarde, ben où tu veux, dans le controleur par ex, il suffit de connecter le menu Save à ta méthode de sauvegarde. Faire de même pour les éventuels menus Open, SaveAs, etc.


----------



## simon (6 Juillet 2004)

Encore une petite question   si je veux utiliser plusieurs controlleur dans mon application comment on fait ?? Mon intuition Java serait de me dire que si je veux communiquer entre les controlleur je dois utiliser des méthodes assesseurs et modificateurs et dans chaque contrôleurs créer un objet pour chaque type de controlleur (puis accéder aux variables grâce aux méthodes). Juste ou faux ?


----------



## mpergand (6 Juillet 2004)

Tes contrôleurs seront instanciés dans IB,chacun ayant les outlets pour les objets qu'il contrôle et éventuellement un outlet pour les autres controleurs si nécessaire. Peut-être avoir un controleur principal qui initialise les autres controleurs? Pour les assesseurs, c'est toi qui vois, si tu veux faire les choses dans les règles de l'art  Pour communiquer entre les objets, il y a aussi les notifications.


----------



## molgow (7 Juillet 2004)

Simon a dit:
			
		

> non parce que sincèrement je connais pas trop ton mode deploy   (arfff le Java c'est quand même mieux   mais non je rigole c'est juste parce que je connais mieux le Java et non je ne veux pas relancer l'éternel combat entre Java et Cocoa)



   

Tu me racontes quoi là? Je capte plus rien du tout, je vois pas le rapport avec ce que je disais!

Je te disais juste que ton appli ne fonctionne pas chez moi. Je la lance et elle quitte immédiatement...

Je suis sur 10.3.4.


----------



## simon (7 Juillet 2004)

molgow a dit:
			
		

> Tu me racontes quoi là? Je capte plus rien du tout, je vois pas le rapport avec ce que je disais!
> 
> Je te disais juste que ton appli ne fonctionne pas chez moi. Je la lance et elle quitte immédiatement...
> 
> Je suis sur 10.3.4.




En fait j'avais pas tellement saisi qu'il existait une différence entre un target pour le dev et pour le deploy mais c'est bon j'ai trouvé à quel endroit il faut modifier le target pour créer une version deploy donc je l'ai recompilé et voilà ce que cela donne (en espérant que cela marche)


----------



## molgow (7 Juillet 2004)

Ok ça marche cette fois 

J'ai testé en vitesse, et la liste tout à gauche buggue un peu. Parfois, certains éléments disparaissent puis se réaffichent en cliquant ailleurs.


----------



## simon (7 Juillet 2004)

En fait ce que je vais faire c'est que maintenant que j'ai un peu mieux compris le principe je vais m'atteler à la même application mais plus complète  Surtout ne vous inquiétez pas je risque d'avoir besoin de vous


----------



## simon (7 Juillet 2004)

molgow a dit:
			
		

> Ok ça marche cette fois
> 
> J'ai testé en vitesse, et la liste tout à gauche buggue un peu. Parfois, certains éléments disparaissent puis se réaffichent en cliquant ailleurs.




Bizarre chez moi je n'ai pas de problème avec la colonne gauche   merci en tout cas d'avoir pris du temps pour tester ma toute chptitte application


----------



## mpergand (7 Juillet 2004)

Je n'ai pas remarqué de problème d'affichage, mais sous Jaguar, ça plante de suite au démarrage   , il y a un moyen simple d'éviter ça: ajouter LSMinimumSystemVersion 10.3.0 à infoPlist (dans XCode)


----------



## mpergand (7 Juillet 2004)

molgow a dit:
			
		

> Tu me racontes quoi là? Je capte plus rien du tout, je vois pas le rapport avec ce que je disais!
> 
> Je te disais juste que ton appli ne fonctionne pas chez moi. Je la lance et elle quitte immédiatement...
> 
> Je suis sur 10.3.4.



Oui, c'est à cause de l'option zerolink, tout le monde se fait pièger avec ça.


----------



## simon (7 Juillet 2004)

mpergand a dit:
			
		

> Je n'ai pas remarqué de problème d'affichage, mais sous Jaguar, ça plante de suite au démarrage   , il y a un moyen simple d'éviter ça: ajouter LSMinimumSystemVersion 10.3.0 à infoPlist (dans XCode)



Oui effectivement dans Interface Builder il m'avait demander pour quel format je voulais sauver et à première vu il y a une imcompatibilité à ce niveau là  merci pour l'ajout dans InfoPlist


----------



## simon (7 Juillet 2004)

Arf je viens découvrir le binding   je veux pas dire mais c'est quand même assez puissant comme truc  vraiment bien le cocoa


----------

