Menggunakan NSString konstan sebagai kunci untuk NSUserDefaults

86

Saya menggunakan NSUSerDefaults untuk menyimpan preferensi pengguna. Saya ingat pernah membaca bahwa menyetel kunci sebagai konstanta adalah ide yang bagus - dan saya setuju. Kode berikut adalah yang saya miliki saat ini:

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

Saya mencoba mengubah ini menjadi:

@implementation Controller

NSString const *kPolygonNumberOfSides = @"polygonNumberOfSides";

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

Meskipun ini berhasil, ini menghasilkan " warning: passing argument 1 of 'objectForKey:' discards qualifiers from pointer target type". Saya ingin menjaga kode saya bebas dari peringatan kompiler. Bagaimana cara memperbaiki peringatan ini?

Olly
sumber

Jawaban:

208

Kamu harus menggunakan:

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

dari pada:

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

Yang pertama adalah penunjuk konstan ke objek NSString, sedangkan yang kedua adalah penunjuk ke objek NSString konstan.

Ini adalah perbedaan yang halus. Peringatan kompilator terjadi karena setObject:forKey:dideklarasikan sebagai berikut:

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

Ini mengharapkan defaultNameargumen menjadi tipe NSString *. Saat Anda meneruskan penunjuk ke sebuah konstanta, Anda telah memberikannya sesuatu yang berbeda.

Pembaruan: Saya ingin menunjukkan bahwa konstanta ini harus didefinisikan seolah-staticolah mereka hanya akan digunakan dari dalam satu file. Saya mengatakan ini karena saya telah mengalami sendiri masalah ini: jika Anda tidak mendeklarasikannya sebagai statis, maka mereka akan ada di namespace global, dan Anda tidak akan dapat menggunakan variabel dengan nama yang sama di file lain. lihat Konstanta di Objective-C untuk informasi lebih lanjut. Untuk menjelaskan dengan contoh, inilah yang saat ini saya gunakan untuk kunci yang hanya perlu saya gunakan dalam satu.mfile:

static NSString * const kSomeLabel = @"...";
e. James
sumber
1
NSString * const fooberfungsi karena NSStringtidak dapat diubah dan penunjuk tidak dapat diubah sehingga tidak pernah dapat diubah, benar? Juga, saya ingat dari C ++ yang constsecara implisit static(pengoptimalan kompiler) jadi tidak perlu memanggilnya. Apakah itu benar juga di sini?
Ternary
32

Jangan gunakan constdengan objek Objective-C, mereka tidak benar-benar dirancang untuk menggunakannya. NSStringobjek (di antara banyak lainnya) sudah tidak dapat diubah secara default berdasarkan desainnya, jadi membuatnya consttidak berguna.

Seperti yang disarankan e.James , Anda dapat menggunakan an NSString * const, yang merupakan penunjuk konstan ke file NSString. Ini sedikit berbeda dari a const NSString *(setara dengan NSString const *), yang merupakan penunjuk ke sebuah konstanta NSString. Menggunakan a NSString * constmencegah Anda menetapkan ulang kPolyuntuk menunjuk ke NSStringobjek baru .

Adam Rosenfield
sumber
Poin bagus tentang penggunaan const. Itulah mengapa banyak class Objective-C memiliki varian "Mutable".
e. James
2
Saya pikir itu constjuga berarti Anda tidak dapat menetapkan ulang. Saya kira saya salah.
Dan Rosenstark
18

Untuk akses dari kelas lain:

.h

extern NSString * const PolygonNumberOfSidesPrefsKey;

.m

NSString * const PolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"

Untuk akses hanya di dalam kelas saat ini:

.m

static NSString * const kPolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"
malhal
sumber
5

Saya akan menyarankan bahkan membuat konstanta lebih deskriptif. Konstanta untuk jumlah sisi poligon bisa berasal dari mana saja. Sebagai saran, bagaimana dengan:

kDefaultsPolygonNumberOfSides;

sebagai gantinya.

Abizern
sumber