87 votes

Utilisation d'une constante NSString comme clé pour NSUserDefaults

J'utilise NSUSerDefaults pour stocker les préférences des utilisateurs. Je me souviens avoir lu quelque part que définir les clés comme des constantes est une bonne idée - et je suis d'accord. Le code suivant est ce que j'ai actuellement :

[[NSUserDefaults standardUserDefaults]
        setObject:[NSNumber numberWithInt:polygon.numberOfSides] 
           forKey:@"polygonNumberOfSides"];

J'ai essayé de changer ça en :

@implementation Controller

NSString const *kPolygonNumberOfSides = @"polygonNumberOfSides";

-(void)savePolygonInfo {
    [[NSUserDefaults standardUserDefaults]
            setObject:[NSNumber numberWithInt:polygon.numberOfSides] 
               forKey:kPolygonNumberOfSides];
}

Bien que cela fonctionne, cela produit des " warning: passing argument 1 of 'objectForKey:' discards qualifiers from pointer target type ". Je tiens à ce que mon code soit exempt d'avertissements du compilateur. Comment puis-je corriger cet avertissement ?

212voto

e.James Points 51680

Vous devriez utiliser :

NSString * const kPolygonNumberOfSides = @"..."; // const pointer

au lieu de :

NSString const * kPolygonNumberOfSides = @"..."; // pointer to const

Le premier est un pointeur constant vers un objet NSString, tandis que le second est un pointeur vers un objet NSString constant.

C'est une différence subtile. L'avertissement du compilateur se produit parce que setObject:forKey: est déclaré comme suit :

- (void)setObject:(id)value forKey:(NSString *)defaultName;

Elle attend le defaultName doit être de type NSString * . Lorsque vous passez un pointeur vers une constante, vous lui donnez quelque chose de différent.

Mise à jour : Je tiens à souligner que ces constantes devraient être définies comme suit static s'ils ne sont utilisés qu'à l'intérieur d'un seul fichier. Je dis cela parce que j'ai moi-même rencontré ce problème : si vous ne les déclarez pas comme statiques, elles existeront dans l'espace de noms global, et vous ne pourrez pas utiliser une variable avec le même nom dans un autre fichier. voir Constantes en Objective-C pour plus d'informations. Pour expliquer par l'exemple, voici ce que j'utilise actuellement pour les clés que je n'ai besoin d'utiliser que dans un seul fichier. .m archivo:

static NSString * const kSomeLabel = @"...";

1 votes

NSString * const foo fonctionne car NSString est immuable et le pointeur est immuable donc il ne peut jamais changer, n'est-ce pas ? De plus, je me souviens que dans le C++, on dit que const est implicitement static (une optimisation du compilateur), il n'est donc pas nécessaire de le signaler. Est-ce également le cas ici ?

33voto

Adam Rosenfield Points 176408

N'utilisez pas const avec les objets Objective-C, ils n'ont pas vraiment été conçus pour l'utiliser. NSString (parmi beaucoup d'autres) sont déjà immuables par défaut en raison de leur conception, donc les rendre const est inutile.

Comme e.J vous pouvez utiliser un NSString * const qui est un pointeur constant vers un NSString . Ceci est subtilement différent d'un const NSString * (équivalent à NSString const * ), qui est un pointeur vers une constante NSString . L'utilisation d'un NSString * const vous empêche de réaffecter kPoly pour pointer vers un nouveau NSString objet.

0 votes

Bonne remarque sur l'utilisation de const. C'est pourquoi beaucoup de classes Objective-C ont des variantes "Mutable".

3 votes

Je pensais que const signifie également que vous ne pouvez pas le réaffecter. Je suppose que je me suis trompé.

0 votes

Compte tenu de votre deuxième paragraphe, je pense que vous devriez modifier votre premier paragraphe. Le fait de ne pas pouvoir réaffecter un identifiant est une utilisation valide, et n'a pas vraiment de rapport avec la mutabilité de l'objet lui-même. Si vous déclarez un NSString comme NSString* const foo = @"bar" et que vous essayez ensuite de le réaffecter, vous obtiendrez l'erreur suivante Cannot assign to variable 'foo'... ce qui est exactement ce que j'espérais en déclarant quelque chose de constant.

18voto

malcolmhall Points 1909

Pour l'accès à partir d'autres classes :

.h

extern NSString * const PolygonNumberOfSidesPrefsKey;

.m

NSString * const PolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"

Pour un accès uniquement à l'intérieur de la classe actuelle :

.m

static NSString * const kPolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"

5voto

Abizern Points 52378

Je suggère même de rendre la constante plus descriptive. Une constante pour le nombre de côtés d'un polygone pourrait provenir de n'importe où. Comme suggestion, que diriez-vous de :

kDefaultsPolygonNumberOfSides;

à la place.

3voto

Sean Murphy Points 1556

Pour plus d'informations sur cette question, il existe un excellent article sur Wikipedia expliquant la syntaxe des constantes avec les pointeurs : http://en.wikipedia.org/wiki/Const_correctness#Pointers_and_references

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X