Questions sur Cocoa

simon

Membre expert
Club iGen
18 Juin 2000
3 669
16
Singapore
www.simonganiere.ch
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 :D
 
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 ?
 
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+
 
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 :

Bloc de code:
- (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 :

Bloc de code:
- (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 :

Bloc de code:
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. :)
 
  • J’aime
Réactions: molgow
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 :D
 
  • J’aime
Réactions: molgow
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.
 
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 ;) :D je vous tiens au courant de la chose ;)
 
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 ;)
 
Il faut utiliser NSAttributedString initWithString:attributes
avec pour attributes un NSDictionary dictionaryWithObject: NSColor forKey: NSForeGroundColorAttributeName
 
Il faut que le delegate de ta NSTableView implémente la méthode:
Bloc de code:
- (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+ ;)
 
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.
 
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 :D :D
 
Ca quitte au lancement. As-tu pensé à compiler en mode deploy ?
 
molgow a dit:
Ca quitte au lancement. As-tu pensé à compiler en mode deploy ?

:confused: non parce que sincèrement je connais pas trop ton mode deploy :siffle: (arfff le Java c'est quand même mieux :D :D 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é:

Bloc de code:
- (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é:
Bloc de code:
- (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 :D
 
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.
 
Encore une petite question :D :D 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 ?
 
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.
 
Simon a dit:
:confused: non parce que sincèrement je connais pas trop ton mode deploy :siffle: (arfff le Java c'est quand même mieux :D :D 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)

:confused: :confused: :confused:

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.
 
molgow a dit:
:confused: :confused: :confused:

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) ;)