web-dev-qa-db-fra.com

Utilisation d'une constante NSString comme clé pour NSUserDefaults

J'utilise NSUSerDefaults pour stocker les préférences de l'utilisateur. Je me souviens avoir lu quelque part que définir les clés comme 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 cela en:

@implementation Controller

NSString const *kPolygonNumberOfSides = @"polygonNumberOfSides";

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

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

85
Olly

Tu devrais 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 subtile différence. L'avertissement du compilateur se produit car setObject:forKey: est déclaré comme suit:

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

Il s'attend à ce que l'argument defaultName soit de type NSString *. Lorsque vous passez plutôt un pointeur vers une constante, vous lui avez donné quelque chose de différent.

Mise à jour: Je tiens à souligner que ces constantes doivent être définies comme static si elles le sont ne sera utilisé qu'à partir 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 statiques, ils existeront dans l'espace de noms global et vous ne pourrez pas utiliser une variable portant le même nom dans un autre fichier. voir Constantes dans Objective-C pour plus d'informations. Pour expliquer par exemple, c'est ce que j'utilise actuellement pour les clés que je n'ai besoin d'utiliser que dans un .m fichier:

static NSString * const kSomeLabel = @"...";
205
e.James

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

Comme e.James l'a suggéré , 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. Utilisant un NSString * const vous empêche de réaffecter kPoly pour pointer vers un nouvel objet NSString.

31
Adam Rosenfield

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

.h

extern NSString * const PolygonNumberOfSidesPrefsKey;

.m

NSString * const PolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSidesPrefsKey"

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

.m

static NSString * const kPolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSidesPrefsKey"
15
malhal

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

kDefaultsPolygonNumberOfSides;

au lieu.

5
Abizern

Pour plus d'informations sur ce problème, il existe un excellent article sur Wikipedia expliquant la syntaxe constante avec des pointeurs: http://en.wikipedia.org/wiki/Const_correctness#Pointers_and_references

3
Sean Murphy