[Résolu] Key-Value Coding: récupération d'une valeur

6ix6ix Membre
juillet 2009 modifié dans API AppKit #1
Bonjour,

J'aimerais me pencher un peu plus sur la technologie Key-Value Coding, et sur ce qu'il est possible de faire (ou de ne pas faire), autre que la récupération d'une valeur de manière " simple ".

Deux problèmes pour exposer ceci, tous les deux basés sur la structure suivante: un NSMutableArray *comptes, contenant des objets Compte (dérivant de NSObject), possédant les variables d'instance NSString *nom et NSNumber *numero.

1)
J'ai à  ma disposition un NSString *unNom, correspondant au nom d'un potentiel Compte; mon but est de savoir si mon tableau comptes contient un objet Compte ayant pour nom unNom. Si tel est le cas, il faut ensuite incrémenter son numero de un.

Pour l'instant, je le fais de cette manière:
NSUInteger index = [[comptes valueForKey:@&quot;nom&quot;] indexOfObject:unNom];<br />	if(index != NSNotFound) {<br />		Compte *leCompte = [comptes objectAtIndex:index];<br />		NSNumber *nb = [[NSNumber alloc] initWithInt:[compte.numero intValue] + 1];<br />		compte.numero = nb;<br />		[nb release];<br />	}


Y a-t-il une possibilité plus directe ? Existe-t-il un moyen de renvoyer directement l'objet Compte (sans passer par l'index) correspondant au nom ?


2)
Dans le même ordre d'idée, j'aimerais récupérer le Compte dont le numero est le plus petit de mon tableau comptes.

J'ai bien un début d'idée avec [comptes valueForKeyPath:@"@min.numero"], mais cela me renverra la valeur NSNumber de ce numero, or je voudrais rester " un niveau au-dessus ", et récupérer le Compte possédant ce numero. Quel est le moyen d'y parvenir ?

Merci pour vos conseils !

Réponses

  • yoannyoann Membre
    22:32 modifié #2
    Tu devrais regarder du coté des NSPredicate qui sont fait pour ça (NSArray dispose d'une méthode pour être filtré avec un prédicat justement)
  • 6ix6ix Membre
    22:32 modifié #3
    Merci, je vais jeter un oeil à  cela !

    Mes deux exemples se rapprochent effectivement plus d'une formulation de requêtes. Ce qui va un pas plus loin de ce que permet le KVC, apparemment.

    Mais je dois dire que mon but est ici avant tout d'avoir une meilleure compréhension du KVC, et de ce qu'il permet de faire. Je reste donc à  l'écoute d'éventuels conseils quant aux " limites " du KVC.
  • yoannyoann Membre
    22:32 modifié #4
    Le KVC en lui même permet "simplement" d'accéder à  tes ivar (qu'elles soit en @property ou pas, qu'elles aient un getter/setter ou pas)

    L'exemple typique c'est le data source d'une table view, je t'ai mis un exemple.

    Pour bien comprendre il faut voir que les identifier des colone sont le nom des ivar.

    En soit le KVC ne sert que rarement tout seul, il est accompagné de KVO et sert pour les binding
  • 6ix6ix Membre
    22:32 modifié #5
    Je vais jeter un oeil à  ton exemple.

    Pour revenir au NSPredication et à  mon 2e exemple, quel serait alors le meilleur moyen pour éliminer de mon tableau comptes l'élément Compte ayant le numero le plus bas ?
  • yoannyoann Membre
    22:32 modifié #6
    Avec ce prédicat : [NSPredicate predicateWithFormat:@SELF.number => 2]

    Autre exemple en fichier joint. Tu devrais jeter un oe“il sur le programming guide des NSPredicate et Key Value Coding, c'est bien expliqué :-)

  • 6ix6ix Membre
    22:32 modifié #7
    dans 1248864572:
    Autre exemple en fichier joint. Tu devrais jeter un oe“il sur le programming guide des NSPredicate et Key Value Coding, c'est bien expliqué :-)


    Je l'ai fait (un peu rapidement), mais je cherche parfois un peu loin... Je me dis qu'il doit sûrement exister une manière de faire meilleure/ plus élégante que je ne connais pas bien dans cocoa, et que je ne voudrais pas rater.  En tous les cas, merci pour les bouts de code.
  • yoannyoann Membre
    22:32 modifié #8
    Après tous dépend les projets. Pour une table view tu as 3 méthodes pour lé remplir

    Avec le data source en faisant tout à  la main, avec le même data source en utilisant le KVC ou avec les binding direct. Perso je me sert des trois en fonction du projet, de ce que j'ai à  faire etc. Les trois méthodes sont bonne, à  toi de voir ce qui est le plus adapté à  ton programme.
  • 6ix6ix Membre
    22:32 modifié #9
    Je continue, si cela ne dérange pas  :P, après plusieurs lectures des documents sur le KVC et NSPredicate.

    dans 1248864572:

    Avec ce prédicat : [NSPredicate predicateWithFormat:@SELF.number => 2]


    Ici je bute sur cet exemple très précis: éliminer de mon tableau comptes l'élément Compte ayant le numero le plus bas. L'exemple que tu donnes et tous ceux que je trouve dans les Programming guide ou sur le Web sont " relativement simples "; on applique une condition sur une certaine variable (=> 2 ici).

    Dans mon cas, j'aimerais pouvoir effectuer une requête plus complexe, puisqu'il s'agit d'obtenir l'objet dont la valeur d'une variable est la plus petite.

    J'ai tenté plusieurs variantes de ceci, sans succès (inspiré des opérateurs KVC):
    [comptes filterUsingPredicate:[NSPredicate predicateWithFormat:@&quot;NOT (@min.SELF.numero)&quot;]];
    


    Avec la réflexion suivante: on ne garde que les éléments dont le numero n'est pas le plus petit (ie on vire tous ceux qui n'ont pas le plus petit numero). Sauf que le format est faux (NSInvalidArgumentException).

    Est-ce possible de la sorte ? Ou alors je dois me résoudre à  trouver d'abord l'(s) élément(s) ayant le plus petit numero, puis les éliminer manuellement du tableau comptes... ?
  • yoannyoann Membre
    22:32 modifié #10
    Il faudra que tu trouve en premier le plus petit numéro via le @min et valueForKey: et qu'ensuite tu l'intègre dans ton format du NSPredicate.

    NSPredicate ne fait que prendre chacun des éléments du tableau et les évaluer par rapport au prédicat, si le prédicat est vrai il garde et renvois un tableau à  la fin
  • 6ix6ix Membre
    22:32 modifié #11
    dans 1248874186:

    Il faudra que tu trouve en premier le plus petit numéro via le @min et valueForKey: et qu'ensuite tu l'intègre dans ton format du NSPredicate.


    Toujours moi, sur le même problème  ;)

    Je pense désormais avoir compris le principe, mais là  je bute inlassablement sur le même problème ("unable to parse the format string"), avec différentes variantes de ce code:
    <br />	[comptes filterUsingPredicate:[NSPredicate predicateWithFormat:@&quot;%K &gt; %@)&quot;, @&quot;SELF.numero&quot;, [comptes valueForKeyPath:@&quot;@min.numero&quot;]]];<br />
    


    Le numero minimal fonctionne, je l'ai testé séparément. J'ai également testé cette manière de faire sur un tableau contenant directement des NSNumber, c'est en ordre. Mais là , le problème a l'air de se poser avec @SELF.numero, pourtant les exemples d'Apple utilisent également les path dans des cas similaires...
  • yoannyoann Membre
    22:32 modifié #12
    Tu as une parenthèse en trop dans ton format j'ai l'impression
  • 6ix6ix Membre
    22:32 modifié #13
    dans 1249047544:

    Tu as une parenthèse en trop dans ton format j'ai l'impression


    J'y crois pas, quel *** !  :o Bon alors en fait il y avait 2 erreurs, la 1e étant qu'il ne faut pas mettre de SELF devant numero; je pense qu'ensuite j'ai fait plein de tests avec SELF, et lorsque j'ai testé sans celui-ci, j'ai alors oublié d'enlever une parenthèse par rapport à  mes multiples essais...

    Merci d'avoir eu l'oeil attentif, je pense en avoir terminé avec ce problème !
Connectez-vous ou Inscrivez-vous pour répondre.