Utilizzo di una costante NSString come chiave per NSUserDefaults


86

Sto usando NSUSerDefaults per memorizzare le preferenze dell'utente. Ricordo di aver letto da qualche parte che impostare le chiavi come costanti è una buona idea - e sono d'accordo. Il codice seguente è quello che ho attualmente:

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

Ho provato a cambiarlo in:

@implementation Controller

NSString const *kPolygonNumberOfSides = @"polygonNumberOfSides";

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

Mentre questo funziona, produce " warning: passing argument 1 of 'objectForKey:' discards qualifiers from pointer target type". Desidero mantenere il mio codice libero dagli avvisi del compilatore. Come posso correggere questo avviso?

Risposte:


207

Dovresti usare:

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

invece di:

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

Il primo è un puntatore costante a un oggetto NSString, mentre il secondo è un puntatore a un oggetto NSString costante.

È una sottile differenza. L'avviso del compilatore si verifica perché setObject:forKey:è dichiarato come segue:

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

Si aspetta che l' defaultNameargomento sia di tipo NSString *. Quando invece passi un puntatore a una costante, gli hai dato qualcosa di diverso.

Aggiornamento: voglio sottolineare che queste costanti dovrebbero essere definite comestaticse dovessero essere utilizzate solo da un singolo file. Dico questo perché mi sono imbattuto in questo problema io stesso: se non li dichiari come statici, allora esisteranno nello spazio dei nomi globale e non sarai in grado di utilizzare una variabile con lo stesso nome in un altro file. vedere Costanti in Objective-C per ulteriori informazioni. Per spiegare con un esempio, questo è ciò che attualmente uso per le chiavi che devo usare solo in un.mfile:

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

1
NSString * const foofunziona perché NSStringè immutabile e il puntatore è immutabile quindi non può mai cambiare corretto? Inoltre, ricordo da C ++ che constè implicitamente static(un'ottimizzazione del compilatore), quindi non c'è bisogno di chiamarlo. È vero anche qui?
Ternario

32

Non usare constcon oggetti Objective-C, non sono stati progettati per usarlo. NSStringgli oggetti (tra molti altri) sono già immutabili per impostazione predefinita in virtù del loro design, quindi realizzarli constè inutile.

Come suggerito da e.James , puoi usare un NSString * const, che è un puntatore costante a un file NSString. Questo è leggermente diverso da a const NSString *(equivalente a NSString const *), che è un puntatore a una costante NSString. L'uso di a NSString * constti impedisce di riassegnare kPolyper puntare a un nuovo NSStringoggetto.


Un buon punto sull'uso di const. Ecco perché molte classi Objective-C hanno varianti "Mutabili".
James

2
Ho pensato che constquesto significhi anche che non puoi riassegnarlo. Credo di essermi sbagliato.
Dan Rosenstark

18

Per l'accesso da altre classi:

.h

extern NSString * const PolygonNumberOfSidesPrefsKey;

.m

NSString * const PolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"

Per l'accesso solo all'interno della classe corrente:

.m

static NSString * const kPolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"

5

Suggerirei anche di rendere la costante più descrittiva. Una costante per il numero di lati di un poligono potrebbe provenire da qualsiasi luogo. Come suggerimento, che ne dici di:

kDefaultsPolygonNumberOfSides;

anziché.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.