NSDictionary : objectForKey et valueForKey:

Philippe49Philippe49 Membre
13:35 modifié dans API AppKit #1
Il semble que cette classe  (abstraite, donc ce n'est pas vraiment cette classe qui la redéfinit ) redéfinit la méthode valueForKey: du KeyValueCoding .
Il y a une différence entre objectForKey: et valueForkey: pour un NSDictionary, mais je n'arrive pas bien à  la formuler.

[size=12pt]objectForKey:[/size]
Returns the value associated with a given key.

- (id)objectForKey:(id)aKey

Parameters
aKey
The key for which to return the corresponding value.
Return Value
The value associated with aKey, or nil if no value is associated with aKey.

Availability
Available in Mac OS X v10.0 and later.
See Also
– allKeys
– allValues
– getObjects:andKeys:
Declared In
NSDictionary.h

[size=12pt]valueForKey:[/size]
Returns the value associated with a given key.

- (id)valueForKey:(NSString *)key

Parameters
key
The key for which to return the corresponding value. Note that when using key-value coding, the key must be a string (see Key-Value Coding Fundamentals).
Return Value
The value associated with key.

[glow=red,2,300]Discussion
If key does not start with “@”, invokes objectForKey:. If key does start with “@”, strips the “@” and invokes [super valueForKey:] with the rest of the key.
[/glow]
Availability
Available in Mac OS X v10.3 and later.
See Also
– setValue:forKey: (NSMutableDictionary)
– getObjects:andKeys:
[glow=red,2,300]Declared In
NSKeyValueCoding.h[/glow]

Réponses

  • 13:35 modifié #2
    Bonjour Philippe,

    Je pense que la différence vient du fait que les listes de propriétés suivent une convention. Celle-ci s'appuie sur un ensemble d'instances pouvant figurer dans un dictionnaire et permettant ainsi la génération d'une liste de propriétés.
    Dans ce cas, le jeu de méthodes à  utiliser est (setValue:forKey , valueForKey). Les instances possibles pour ce cas sont NSData, NSDictionary, NSDate, NSArray, NSString et NSNumber.

    Puisque tous les instances des autres classes peuvent également être intégrées dans un dictionnaire, nous devont employer l'autre jeu de méthodes (setObject:forKey, objectForKey). Ce type de dictionnaire n'étant pas compatible avec les listes de propriétés. Une vérification simple consiste à  enregistrer un dictionnaire (pList-like) et un autre (not p-List like).
  • ChachaChacha Membre
    13:35 modifié #3
    J'ai une autre explication.
    objectForKey:, c'est une méthode de NSDictionary. Bon.
    À côté de ça, Cocoa implémente le Key-Value coding via valueForKey:, déclarée dans NSObject.
    Le souci, c'est d'être cohérent. Or, pour être cohérent, il est logique que valueForKey: se comporte comme objectForKey: dans un dictionnaire.
    Sauf...
    Sauf que, supposons que l'on crée une sous-classe de NSDictionary, cette sous-classe ayant un attribut "toto" de type double. Le key-value coding nous dit que valueForKey:@toto devrait renvoyer ce double, alors que l'on vient de dire qu'il devrait renvoyer la valeur associée à  la clef "toto" contenue dans le dictionnaire ! Pour s'en sortir, on peut utiliser le @ :
    valueForKey:@toto renverrait la valeur associée à  la clef
    valueForKey:@"@toto"; renverrait le double qu'est l'attribut toto.

    Mais comme NSDictionary fait partie d'un class-cluster, je n'ai pas pu le dériver pour tester. Qu'à  cela ne tienne ! N'oublions pas que le key-value coding peut être utilisé pour des attributes "factices", c'est-à -dire pour appeler des méhodes.
    Voici donc un exemple concret :


    NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:@toto, @count, nil];
    NSLog(@%@", [dict valueForKey:@count]);  //affiche "toto"
    NSLog(@%@", [dict valueForKey:@"@count";]); //appelle la méthode -(int)count et affiche 1.


    +
    Chacha
  • Philippe49Philippe49 Membre
    13:35 modifié #4
    Chacha.
    La définition spécifique du valueForKey: est ainsi la possibilité d'utiliser pour clés du dictionnaire des identifiants qui sont aussi des noms de méthode, ou, plus généralement, qui ont un sens dans le KVC

    Je n'avais pas formulé aussi clairement cette possibilité du KVC de prendre comme clé des noms de méthode, bien que l'ayant vu à  l'action lors de binding sans que des variables d'instances soient physiquement définies pour la clé du binding.


    #import <Foundation/Foundation.h>
    int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool=[[NSAutoreleasePool alloc] init];
    NSString * string=@Coucou;
    NSLog(@%@",[string valueForKey:@length]);
    [pool drain];
    return 0;
    }

    % gcc pgm.m -o pgm -framework Foundation
    % pgm
    2008-08-25 10:58:22.774 pgm[207:10b] 6
    %

  • 13:35 modifié #5
    Alors là  c'est très intéressant ! Chapô et merci pour cette indication  :o
  • Philippe49Philippe49 Membre
    août 2008 modifié #6
    Autre exemple pour le KVC via les méthodes :

    #import <Foundation/Foundation.h>
    @interface ClassA:NSObject {
    NSString * name;
    ClassA * child;
    }
    -(NSInteger) longueur;

    @end
    @implementation ClassA
    -(NSInteger) longueur { return [name length]; }
    @end

    int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool=[[NSAutoreleasePool alloc] init];
    // Le fils de "a" est "aPitchoune" 
    ClassA * a=[[[ClassA alloc] init ] autorelease];
    ClassA * aPitchoune=[[[ClassA alloc] init ] autorelease];
    [a setValue:aPitchoune forKey:@child];

    // a s'appelle "I am A",  aPitchoune s'appelle "Pitch"
    [a setValue:@I am A forKey:@name];
    [aPitchoune setValue:@Pitch forKey:@name];
    [aPitchoune release];

    // On teste les méthodes longueur avec valueForKey et valueForKeyPath
    NSLog(@%@",[a valueForKey:@longueur]);
    NSLog(@%@",[a valueForKeyPath:@child.longueur]);


    [pool drain];
    return 0;
    }



    % gcc pgm.m -o pgm -framework Foundation
    % pgm
    2008-08-25 11:34:44.031 pgm[335:10b] 6
    2008-08-25 11:34:44.034 pgm[335:10b] 5
    %

Connectez-vous ou Inscrivez-vous pour répondre.