# [cocoa] NSTableView et les données



## 6ix (21 Juillet 2005)

Bonjour,

Je dois vous avouer que je suis un peu perdu, je cherche, je cherche, en vain...   
Pour résumer la chose, j'ai une NSTableView qui contient des articles, possédant chacun une date (d'ajout à cette table), et voilà ce que j'aimerais pouvoir faire (en plus d'ajouter/supprimer un article, ce j'ai déjà codé):

1) trier ma table par rapport à la date (apparemment c'est loin d'être facile...?!)

2) afficher les articles d'un seul jour/mois/année; c'est-à-dire que j'aimerais que, si l'utilisateur choisit d'afficher "par mois", pour le mois de juin, par exemple, ma table n'affiche que les articles du mois de juin (mes données sont sous forme de NSMutableArray contenant des NSDictionary). En fait, c'est un peu comme si dans iTunes on choisit un artiste, et la table n'affiche que les chansons de l'artiste en question.
Je vois (en gros) la chose comme ceci: pour chaque élément (article), récupérer la date (le mois, si le classement se fait "par mois"), tester si cette date correspond à celle entrée par l'utilisateur, et afficher ou non l'élément dans l'article selon cette date.

J'ai trouvé plusieurs tutos, mais jamais expliquant ce que je voudrais faire... C'est surtout sur la fin que je fais du surplace, "afficher ou non l'élément"; ou alors cocoa propose carrément une méthode couvrant le test et l'affichage?!? Mais je ne sais pas trop avec quoi traiter: NSTableView? DataSource? J'ai vraiment aucune idée de quelles méthodes utiliser, et je me retrouver à essayer à lire la docu xcode de long en large sans vraiment savoir par où aller! 
A noter que je code en Java, mais tout tuto ou exemple en Obj-C me serait utile; alors si vous avez des bouts de code (obj-c ou java), des exemples, des tutos ou explications (français comme anglais), je suis preneur!
Merci


----------



## Ludopac (21 Juillet 2005)

Je t'ai fait rapidement un petit projet qui répond à ta première demande (trie en fonction de la date). Par contre j'avais pas lu au départ que tu programmais en Java (l'exemple que j'ai fait est en Objectif C). J'ai fait ça rapidement donc l'exemple n'est pas parfait 

Télécharger l'exemple en Objectif C 

J'ai utilisé un nouvel objet NSDatePicker dans l'interface donc l'application compilée ne marchera que sous Mac OS X.4. 
Mais si tu n'as pas encore ce système, tu peux tout de même accéder au code je pense.

Pour ta seconde requète, n'ayant pas encore eut à programmer cela je ne peux pas trop t'aider...


----------



## BooBoo (22 Juillet 2005)

Je n'ai pas de réponse toute faites pour le 2nd point, mais en regardant dans l'aide de XCode, il y a une nouvelle méthode pour NSArray:

```
filteredArrayUsingPredicate:
- (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate

Evaluates the predicate against the receiver?s content and returns a new array containing the objects that match.
```

J'ai l'impression que cela peut être très utile pour filtrer un tableau suivant certaines conditions
Il y a dans l'aide un guide de programmation des prédicats avec des examples. Cette fonctionnalité est apparu avec OS X.4.


Sinon, il faut faire manuellement une seconde table en testant chaque élément de ta table principale. Cette seconde table serait généré quand les conditions d'affichage serait modifiés, et c'est cette table qui serait affichée.

Si tu veux un peu plus d'aide, je peux ce soir faire un exemple...


----------



## 6ix (22 Juillet 2005)

Je vais essayer ça après, merci déjà!    

J'utilise justement un NSDatePicker, donc tant mieux! C'est un peu bête, j'aurais dû spécifier dès le départ que je le faisais en Java... Mais je me débrouillerai pour "traduire", à moins que certaines méthodes soit totalement différentes entre obj-c et java; c'est d'ailleurs un peu le cas avec les dates, où il faudrait passer par NSCalendar en plus de NSDate, mais cela n'existe pas avec java... je fais donc un petit jonglage NSDate  (-> Date (pure java)) -> Calendar (pure java), mais bof!

Pour le 2e, je vais voir ce que je peux faire, cette méthode peut être intéressante. Sinon effectivement, jongler avec des tableaux est une possibilité.
Je ne dis pas non pour un exemple, mais je ne voudrais pas abuser non plus... :rose: 

J'en suis au début de Cocoa, et parfois j'ai encore un peu de peine à cerner ce que propose Cocoa; je m'attends à une méthode toute faite en liaison avec un élément d'interface, mais c'est un peu exagéré de ma part! Au contraire parfois je reste trop scotché à du pure java, ne voyant pas une facilité de Cocoa... Mais bon, c'est à force d'utiliser Cocoa que ça viendra; la seule chose, qui est normale également, c'est qu'il est plus facile de trouver une explication/un exemple sur une classe de l'api java que sur une classe cocoa (java plus encore)...

Je reste encore ouvert à toute autre possibilité.


----------



## BooBoo (23 Juillet 2005)

Voilà, j'ai fait un petit exemple afin de filtrer une liste avec les prédicats
Vu que ça m'intéresse aussi, autant que ça serve à qqn d'autre...
mais moi aussi, c'est en ObjectiveC

j'ai un peu galerer avec les dates pour les prédicats, mais j'ai trouvé une solution
voilà mon projet: predicat.zip 

coreData devrait pouvoir simplifier encore plus les choses, mais je ne connais pas encore...


----------



## 6ix (23 Juillet 2005)

Merci Booboo, je regarderai ça demain.

Par contre, Ludopac, j'ai encore qques petits soucis... j'ai compris la manière de procéder de ton exmple, mais je ne connais pratiquement rien d'objective-c, et ma "traduction" vers java est donc un peu laborieuse; pourrais-tu m'éclaircir sur 1-2 choses stp (ou qqun qui connait java)?


> (IBAction)addArticleid)sender {
> Article *newArticle = [[Article alloc] init];
> [newArticle setDate:[dateField dateValue]];
> [newArticle setArticle:[articleField stringValue]];
> ...





> (NSComparisonResult)comparaisonDateArticle *)articleAComparer {
> return [date compare:[articleAComparer date]];


Ici, si j'ai bien saisi, le principal réside dans cela: on construit un selector avec comme argument le nom de la méthode (ah oui, au fait ce constructeur est deprecated, version java en tout cas!), cette méthode effectue la comparaison, et le tableau "listeArticles" est ensuite trié...(?) Malheureusement pour moi, NSComparisonResult n'existe pas version java, et NSSelector fonctionne qque peu différemment; j'ai +/- trouvé comment faire, mais je ne comprends pas trop le contenu de la méthode de comparaison: l'argument est l'article à comparer; mais il est comparé avec quoi? comment cette méthode fonctionne-t-elle? Là c'est la syntaxe obj-c qui m'empêche un peu de comprendre... :rose: 

PS: concernant les dates, j'ai trouvé la classe NSGregorianDate qui simplifie bien des choses, ça évite de passer par du pure java comme je me l'imaginais!


----------



## Ludopac (23 Juillet 2005)

6ix a dit:
			
		

> Ici, si j'ai bien saisi, le principal réside dans cela: on construit un selector avec comme argument le nom de la méthode (ah oui, au fait ce constructeur est deprecated, version java en tout cas!), cette méthode effectue la comparaison, et le tableau "listeArticles" est ensuite trié...(?)



Oui c'est bien cela.
Je n'ai pas eut d'indication comme quoi cette méthode était obsolète lors de la compilation. Etrange...




			
				6ix a dit:
			
		

> Malheureusement pour moi, NSComparisonResult n'existe pas version java, et NSSelector fonctionne qque peu différemment; j'ai +/- trouvé comment faire, mais je ne comprends pas trop le contenu de la méthode de comparaison: l'argument est l'article à comparer; mais il est comparé avec quoi? comment cette méthode fonctionne-t-elle? Là c'est la syntaxe obj-c qui m'empêche un peu de comprendre... :rose:




En fait la méthode *sortUsingSelector* procède ainsi :

- elle parcourt le tableau (ici *NSMutableArray*)

- pour chaque objet contenu, elle fait appel à la méthode *comparaisonDate* avec en argument un autre objet du tableau (ils sont tous passés un par un)

- la méthode *comparaisonDate* compare le receveur (l'élément courant que l'on compare avec tous les autres) et celui passé en argument.

- elle renvoi un *NSComparisonResult* qui peut être _NSOrderedAscending_ (élément passé en arguments est plus grand), _NSOrderedSame_ (élément passé en arguments est identique), ou _NSOrderedDescending_ (élément passé en arguments est plus petit)

- en fonction de la valeur renvoyée, le receveur est déplacé dans le tableau


----------



## mpergand (23 Juillet 2005)

C'est le bazar au niveau de la doc java !

J'ai Xcode 2.1 et NSPredicate n'apparaît dans la doc des classes du foundation kit, par contre elle existe sur la doc du site Apple:
http://developer.apple.com/document.../Java/index.html#//apple_ref/doc/uid/20001092

ainsi que NSExpression !

Pour les NSComparisonResult, ils sont définis dans NSComparator, mais en WebObjects !! et introuvablent en cocoa-java   

NSOrderedAscending = -1
NSOrderedSame=0
NSOrderedDescending=1


----------



## 6ix (23 Juillet 2005)

mpergand a dit:
			
		

> C'est le bazar au niveau de la doc java !
> 
> J'ai Xcode 2.1 et NSPredicate n'apparaît dans la doc des classes du foundation kit, par contre elle existe sur la doc du site Apple:
> http://developer.apple.com/document.../Java/index.html#//apple_ref/doc/uid/20001092
> ...



Tu n'as peut-être pas téléchargé la dernière version de la documentation? Je m'étais dit la même chose avant de le faire... Elle est dispo sur le site apple adc developper.

Pour NSComparisonResult, je vais voir de ce côté-ci alors...


----------



## 6ix (23 Juillet 2005)

Je suis arrivé à qque chose pour trier les dates, mais cela ne marche pas...


> articleList.getArticles().sortUsingSelector(new NSSelector("compare", new Class[] {NSDate.class}));


articleList.getArticles() renvoie un NSMutableArray, que je trie avec sortUsingSelector, en prenant la méthode "compare" de NSDate... Cela marcherait sans doute si mon NSMutableArray contenait des NSDate (?), mais là ce n'est pas le cas, puisqu'il contient des NSMutableDictionary composés de 3 "éléments", dont 1 est la date de l'article en question.
Si mon raisonnement est correct, il faudrait donc que la comparaison ne se fasse pas directement sur le NSMutableArray, mais sur la date contenue dans le dictionnaire, lui-même dans le NSMutableArray; je peux accéder à la date avec objectForKey("Date") depuis le NSMutableDictionary, mais ensuite, comment obliger la comparaison sur cette date récupérée??

De même pour mon 2e problème; en reprenant l'exemple, j'arrive à qque qui tient la route, mais bute sur un truc dans la méthode de filtre:


> public void setFilter() {
> NSPredicate predicate = NSPredicate.predicateWithFormat("=", new NSArray(((NSMutableDictionary)articleList.getArticles()).objectForKey("Date"));
> 
> // lance le filtre sur toute la liste
> ...


La façon de construire le predicate n'est pas correcte, et je ne peux pas me calquer sur l'obj-c qui utilise un NSString avec la méthode stringWithFormat... Que faut-il donc utiliser en java?


> NSString *str;
> NSPredicate *predicate;
> NSString *op  = [typeFilterComboBox stringValue];
> // Pour la date, compare les dates par interval en flottant
> ...



Je crois que je vais me mettre plus vite que prévu à l'obj-c...


----------



## BooBoo (24 Juillet 2005)

j'ai amélioré mon exemple en créant le prédicat sans passer par une chaîne. C'est beaucoup plus facile, surtout avec les dates...
Il est téléchargeable au même endroit que le précédent.


----------



## Ludopac (24 Juillet 2005)

BooBoo a dit:
			
		

> coreData devrait pouvoir simplifier encore plus les choses, mais je ne connais pas encore...



Voici deux bon tutoriaux sur coreData : http://www.cocoadevcentral.com/articles/000085.php et http://www.cocoadevcentral.com/articles/000086.php.

Et effectivement ça simplifie encore beaucoup les choses


----------

