Comment lié un NSMutableArray avec un NSTableView ?

boobool

Membre confirmé
19 Juin 2011
56
1
44
Salut,

Jusqu'à présent je nageai en buvant la tasse mais là je suis à la limite de la noyade :D
J'ai un joli NSMutableArray dans mon code, un joli NSTableView, un NSTextFIeld et un joli NSButton dans mon interface. Comment faire pour que : quand je rentre un texte dans le textfield puis que je clique sur le bouton, mon array se remplisse, remplissant dans la foulé le tableview à l'image de l'array.
La partie array bouton textfield ça va mais, comment remplir le tableview ?
 
Pas très claire ta question...
Montres ton code existant et sois un peu plus clair sur ce que tu souhaites... Si j'ai bien compris ce qui te manque, c'est le remplissage de la tableview ? :(
 
Oui c'est ça, comment remplir le tableview à partir de l'arraymutable.
L'array fonctionne, par contre, pas le tableview.
J'ai retiré tout le code testé qui marche pas par rapport au tableview.
Pour commencer avec xcode/cocoa j'évite les multiples fichier controller, view .h et .m je verrais plus tard les classes et objets quand j'aurais bien compris la base de la base (je ne sais pas si c'est comme ça qu'il faut faire ?)
J'ai trouvé un tuto en passant par un NSArrayController mais il y a plein de manips avec l'interface et j'ai du mal à m'y retrouver avec tous ces nouveaux termes.
J'aimerais utiliser le binding mais si c'est trop chaud pour commencer, on met de côté.
le .h :
Bloc de code:
#import <Cocoa/Cocoa.h>

@interface Gestion_stocks_TPAppDelegate : NSObject <NSApplicationDelegate> {
@private
    NSButton *monBouton;
    NSTextField *monChampsTexte;
    NSTableView *monTableView;
    NSMutableArray *monArrayMutable;
}

@property (assign) IBOutlet NSButton *monBouton;
@property (assign) IBOutlet NSTextField *monChampsTexte;
@property (assign) IBOutlet NSTableView *monTableView;
@property (assign) IBOutlet NSMutableArray *monArrayMutable;

- (IBAction)AjouterAuTableView:(id)sender;

@end

le .m :
Bloc de code:
#import "Gestion_stocks_TPAppDelegate.h"

@implementation Gestion_stocks_TPAppDelegate

@synthesize monBouton;
@synthesize monChampsTexte;
@synthesize monTableView;
@synthesize monArrayMutable;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    
}

-(void)AjouterAuTableView:(id)sender
{
    monArrayMutable = [[[NSMutableArray alloc] init] autorelease];
    [monArrayMutable insertObject:[monChampsTexte stringValue] atIndex:0];
    NSLog(@"%@ - %@",[monArrayMutable objectAtIndex:0],[monChampsTexte stringValue]);//ok
    //que faire pour envoyer l'array au tableview ?
}

@end
 
Tu as raison d'eviter les controllers. Cela ne sert a rien. C'est comme les bindings, c'est juste pour decorer. :siffle:

As-tu cree un ArrayController dans ton XIB ? L'as-tu parametre? As-tu etabli les connexions entre ce controller et ton TableView via l'inspecteur ? Au fait, ta source de donnees, ou est-elle? Car le texte que tu tapes dans le TextField pour remplir ton tableau, tu dois le stocker quelque part physiquement. Exemple: fichier XML, SQLite... Utilises-tu Core Data ?
 
Dernière édition:
Lio : comme je te dis je débute, donc j'essaye de commencer par le simple pour apprendre.
As-tu cree un ArrayController dans ton XIB ?
oui
L'as-tu parametre?
j'ai essayé
As-tu etabli les connexions entre ce controller et ton TableView via l'inspecteur ?
j'ai essayé
Au fait, ta source de donnees, ou est-elle?
Pour l'instant la source de donnée est l'array, par la suite une table mysql.
Utilises-tu Core Data ?
Non je ne sais pas encore ce que c'est.
Cathy : merci j'ai commencé cette doc mais ça fait beaucoup a assimiler d'un coup donc ta piste m'est d'un grand secours, merci.
 
C'est vrai que la doc apple est un peu repoussante au premier abord mais il faut prendre les procédures les unes après les autres...
Voici quelques idées de code pour les procédures les plus importantes :

Bloc de code:
- (int)numberOfRowsInTableView:(NSTableView *)tableView
{
    return [monArray count];
}

- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row
{
    return [monArray objectAtIndex:row];
}

et surtout, si le contenu de ton array a changé :

Bloc de code:
[tableView reloadData];

Si tu as un doute sur les procédures, en particulier savoir quand elle sont appelées, tu peux mettre un NSLog pour pister le passage dans chaque procédure.
Bon courage...:D
 
@boobool

Tu devrais essayer Core Data. Plusieurs programmeurs experimentes sur ce forum te le deconseilleront car en cas de probleme, c'est parfois difficile a debugger. Mais vu que ton application est fort basique, tu obtiendras un resultat utilisable plus vite en utilisant Core Data car cela te permet de faire une application de donnees en t'epargnant pas mal de lignes de code.

Evidemment, pour apprendre, tu as interet a tout essayer pour comprendre la mecanique d'une application, mais tu pourras toujours le faire apres, en t'exercant a recoder ton appli selon la (vieillissante) methode classique.

Mais essaye de trouver un tutoriel en francais, qui te presente succinctement Core Data. Il y en a quelques-uns et ils contiennent generalement un exemple tout a fait similaire a ta petite application. Tu verras que tu pourras remplir ton TableView les doigts dans le nez. Cela te permettra de maitriser plus vite les controleurs et "bindings" essentiels (liens entre le moteur de ton application et les elements graphiques presentant les donnees a l'ecran) sans devoir maitriser Objective-C.

Tu auras la satisfaction de voir tres vite ton application fonctionner, et ce sera encourageant pour l'avenir, plus que secher des heures et des nuits pour faire un petit truc, avec le risque d'en avoir ras le bol et d'arreter. Vu que tu veux faire une appli avec stockage des donnees en SQL (je presume que tu veux parler de SQLite), cela te sera encore plus simple aussi pour la base de donnees.

- Recommence un projet d'appli en incorporant Core Data.
- Definis tes champs et types de donnees dans le modele.
- Repere dans le code les lignes qui definissent ton "store" (le fichier stockant les donnees). Par defaut il est en XML; remplace-le par SQLite.
- Dans ton fichier XIB, ajoute un ArrayController, parametre-le dans l'inspecteur, fais les liens avec les elements de ton interface (bouton, TextField, TableView)...

:zen:
 
Dernière édition:
Cathy,je suis désolé de vous ennuyez mais après une nuit de réflexion, je comprends pas a quoi sert ce code et comment s'en servir, car a mon sens ce sont des méthodes et aucune idée de comment s'en servir. Si c'était possible d'avoir une traduction en français de ces méthodes ce serait sympa et ça me ferait probablement faire un grand pas dans la compréhension de cocoa.
Par exemple tableView, est ce le nom de la méthode ? Comment appel t-on cette méthode ?
 
Il y a deux méthodes pour lier un NSArray à un NSTableview :
- l'ancienne, citée par Cathy qui consiste à designer un delegate pour lequel tu renseignes un certain nombre de méthodes dans son code.
- la "nouvelle" qui utilise les bindings via un NSArrayController et où tout se fait dans IB, pas de code à ajouter.

Le problème est que les bindings deviennent rapidement une usine à gaz et tu peux passer des heures à chercher où tu as oublié de mettre ton lien pour que cela fonctionne.
La première méthode est plus adapté à un débutant et bien plus facile à débugger.
 
Perso je n'utilise pas les bindings... parce que j'aime bien voir ce que je code... et peut-être aussi parce que je suis encore dans la catégorie "débutants". :D

Pour répondre à ta question Boobool, ces méthodes sont à implémenter directement dans ton .m, sans oublier de déclarer ton delegate...
En particulier, la méthode 'numberOfRowsInTableView' permet au tableview de savoir combien de lignes elles doit définir, ici cela correspond aux nombres d'items de ton array [monArray count]. Ce qui déclenche autant d'appels de la méthode 'objectValueForTableColumn', ou chaque cellule est remplie avec l'item n° row de ton array.

En conséquence, si ton array subit des modifications (ajout d'un item, suppression ou modification), tu dois invoquer l'appel de la méthode reloadData.

De même, lorsque l'utilisateur sélectionne une cellule de ta tableview, il te faut programmer pour indiquer que c'est l'item row de ton array qui a été sélectionné. Rien de plus simple...

Bon courage :cool:
 
Je crois que j'ai enfin compris pourquoi ça marche pas ! Ce code c'est pour iphone IOS et moé je code pour OSX :rateau:
Donc voilà.
 
Bon je crois que j'ai trouvé finalement pourquoi ça ne marche pas, voilà ce que j'ai lu dans la doc apple :
Note: This method is optional if your application is using Cocoa bindings for providing data to the table view, otherwise it must be implemented.
Availability


  • Available in Mac OS X v10.0 and later.
  • Available as part of an informal protocol prior to Mac OS X v10.6
Je suis sous 10.6 et je ne sais pas si mon application utilise le binding cocoa ...
Dans tout les cas je crois qu'il faut que je fasse quelque chose par rapport part of internal protocol mais quoi ? Et comment faire pour l'implémenté du coup ?

Je crois que cocoa aura ma peau :D
 
Il y a deux méthodes pour lier un NSArray à un NSTableview :
- l'ancienne, citée par Cathy qui consiste à designer un delegate pour lequel tu renseignes un certain nombre de méthodes dans son code.
- la "nouvelle" qui utilise les bindings via un NSArrayController et où tout se fait dans IB, pas de code à ajouter.
Si tu ne sais pas comment tu as lié ta table et ton tableau, on ne peut pas grand chose pour toi :rateau:
 
Juste pour être sur, je veux remplir le tableview (en particulier une colonne) et pas remplir l'array à partir du tableview, vous avez bien compris ça ?
Il n'y a pas un truc du style montableau colonne 1 index 1 = montexte ?
ou même vu qu'une colonne doit ressemblé a un array, macolonne = monarray ?
Vous allez pas me faire retourner sous windows quand même !
 
Au vu de la maniere dont tu t'exprimes, je crois que c'est toi qui n'as pas compris comment cela fonctionne. :p:rateau:
Mais bon, tu es debutant. C'est le metier qui rentre :D

Au depart, tu as un champs texte, un bouton et un tableau que tu veux utiliser comme ceci, si j'en crois la maniere dont tu presentes les choses au debut:
1. taper du texte dans la case
2. cliquer sur le bouton pour ajouter le texte au tableau
3. et quand tu tapes un nouveau texte, tu cliques encore et le texte s'ajoute sur la ligne suivante dans le tableau
4. puis tu veux sauver cela dans une base SQLite, mais plus tard. quand tu t'y connaitras mieux

Tu penses a l'envers! voila comment cela fonctionne:
1. cliquer sur le bouton. Cela ajoute une ligne vide au tableau.
2. taper le texte dans le champ TextField
3. taper sur Enter et le texte remplira la ligne vide dans le tableau.
Eventuellement, ajouter un deuxieme bouton "Supprimer" pour retirer des lignes du tableau.

Comment proceder? Voici une suggestion, tu en fais ce que tu veux.

1. Cree un nouveau projet. Utilise CORE DATA. Je ne perds plus mon temps a argumenter sur le bien/mal de cette technologie.
2. Dans ton AppDelegate.m, repere "NSXMLStoreType" et remplace par "NSSQLiteStoreType".
3. Dans ton projet il y a un fichier Xcdatamodel. C'est la structure de tes donnees. Ouvre-le.
4. Dedans, cree une nouvelle Entity (c'est la table de tes donnees).
5. Juste a droite, ajoute un Attribute (c'est le champs correspondant a ta colonne dans le tableau. Parametre son type = string. Sauve.

6. Dans Interface Builder (ou toujours Xcode si tu utilises Xcode 4), ajoute a ton fichier XIB un ArrayController que tu parametreras dans l'inspecteur:
=> onglet Attributes:
Mode=Entity
Entity name=nom de l'entity dans ton xcdatamodel
Cocher "Prepares content"
=> onglet Bindings / Parameters:
Bind to "_AppDelegate"
Model Key Path=managedObjectContext

7. Sur la fenetre de ton programme, ajoute un TableView, un TextField et un Button.
Selectionne le button et clic+drag vers l'icone d'ArrayController: choisir "add".

8. Double-clique sur la colonne du tableau. Dans l'inspecteur, onglet Bindings / Value:
Bind to "le nom de ton ArrayController".
Controller Key=arrangedObjects.
Model Key Path="le nom de ton "attribute" dans l'entity que tu as cree (xcdatamodel).

9. Selectionne le TextField. Dans l'inspecteur, onglet Bindings / Value:
Bind to "le nom de ton ArrayController".
Controller Key=selection.
Model Key Path="le nom de ton "attribute" dans l'entity que tu as cree (xcdatamodel).

Sauve et compile.

--- EDIT #1 pour ajout
Xcode cree automatiquement ton fichier SQlite vide. Le nom par defaut est "storedata" (verifier dans le code d'AppDelegate.m).
Si tu modifies ta structure de donnees en cours de projet, quand tu compiles ton prog, il te donne un message d'erreur. Normal. Il faut supprimer le fichier manuellement pour qu'au prochain lancement de ton appli, un nouveau fichier vierge soit recree, selon ta nouvelle structure de donnees.
ton fichier SQLite se trouve dans /Ton_nom/Lirary (Bibliotheque en francais)/Application Support/ton_projet/

--- EDIT #2 CoreData
Apres tout, je vais encore commenter sur ce sujet.
CoreData est une techno inventee par Apple pour simplifier la programmation de donnees. Elle est surtout adaptee aux applications de bases de donnees et ne convient pas a tous les types de programme.
Apple, dans ses seminaires, recommande "vivement" de l'utiliser quand le contexte s'y prete, au lieu de continuer de coder a l'ancienne.
Ne pas l'utiliser, c'est faire comme ces entreprises qui ne veulent pas passer a Windows 7 et preferent rester sous XP parce qu'elles sont trop habituees a Internet Explorer 6. :rateau:

Tout specialement, le debutant a interet a utiliser CoreData car il se trouve face a une montagne de connaissances a maitriser avant de pouvoir obtenir un petit quelque chose de fonctionnel. C'est infernal ! CoreData lui permet de reduire l'intensite de sa migraine :p en le dispensant de pas mal de lignes de code. La satisfaction de voir rapidement une petite appli fonctionnelle, en ayant l'occasion de survoler une variete de choses permettant de voir comment une app pour Mac fonctionne, comment on programme avec Xcode, quelles sont les outils et les technologies d'Apple.

Ensuite evidemment, une fois a l'aise avec ces outils, mettre les mains dans le cambouis et faire de l'Objective-C pur et dur, et aussi du C, en grignotant la matiere progressivement.
:zen:
 
Dernière édition:
Juste pour être sur, je veux remplir le tableview (en particulier une colonne) et pas remplir l'array à partir du tableview, vous avez bien compris ça ?
Il n'y a pas un truc du style montableau colonne 1 index 1 = montexte ?
ou même vu qu'une colonne doit ressemblé a un array, macolonne = monarray ?
Vous allez pas me faire retourner sous windows quand même !

C'est exactement ce que font les méthodes que je t'ai envoyé (objectValueForTableColumn et numberOfRowsInTableView). Mais peut-être n'a tu pas déclaré le protocole ? <NSTableViewDelegate>
 
YEAEAEAEYAEYEAY :up::up::up::up::up:
Mille merci grand maitre ça fonctionne et cerise sur le gâteau : ça enregistre tout dans un fichier !!!!!
Maintenant je vais tenté de comprendre tout ça.
Par rapport a tes edits, je suis 100% d'accord vu que mon objectif est de faire un petit programme qui gère des données. S'il y a des outils qui simplifies les choses et font aller plus vite, pourquoi s'en passer, surtout si ce sont de bons outils. Enfin en ce qui me concerne mon objectif est de faire un programme qui fonctionne, le jour ou j'aurais besoin d'avoir un objet qu'apple n'a pas fait je verrais pour le coder :D (dans un siècle ou deux :D)
Et donc si j'ai compris le xdatamodeld est une sorte de concepteur de base de données ? C'est génial ! tout en un le XCode.
Encore merci :)
 
Boobool,

Content que cela marche et que tu apprecies. Maintenant, analyse tout et essaye en effet de comprendre comment ces liaisons fonctionnent. C'est utile d'avoir une approche globale des choses, la comprehension du modele MVC (Model/View/Controller), c'est a dire des relations entre ta base de donnees, l'interface (ta fenetre avec le bouton, le tableau etc...) et le "moteur" de l'application (ton code dans les fichiers h/m). Et aussi a bien repartir ton code dans differents fichiers h/m (pas tout mettre dans ton AppDelegate par exemple), des fichiers distincts pour les classes, des fichiers pour les controllers....

Je suppose que tu t'es rendu compte que tu peux directement taper le texte dans la case du tableau en double-cliquant sur la cellule, sans devoir passer par ton champ TextField. Mais je l'ai inclus dans l'exemple puisque tu as fait de meme au depart.

Maintenant refais ton appli sans CoreData, en codant tout a la main. Il est evidemment essentiel d'apprendre l'Objective-C. Vas-y progressivement. De toute facon, meme avec CoreData, tot ou tard tu devras coder, au fur et a mesure que ton appli se complexifie.
:zen:;)
 
Dernière édition: