NSUserDefaults için anahtar olarak sabit bir NSString kullanma


86

Kullanıcı tercihlerini saklamak için NSUSerDefaults kullanıyorum. Anahtarları sabitler olarak ayarlamanın iyi bir fikir olduğunu bir yerde okuduğumu hatırlıyorum - ve katılıyorum. Aşağıdaki kod şu anda sahip olduğum şey:

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

Bunu şu şekilde değiştirmeyi denedim:

@implementation Controller

NSString const *kPolygonNumberOfSides = @"polygonNumberOfSides";

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

Bu işe yararken, " warning: passing argument 1 of 'objectForKey:' discards qualifiers from pointer target type" üretir . Kodumu derleyici uyarılarından uzak tutmak istiyorum. Bu uyarıyı nasıl düzeltebilirim?

Yanıtlar:


208

Kullanmalısın:

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

onun yerine:

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

Birincisi, bir NSString nesnesine sabit bir göstericidir, ikincisi ise sabit bir NSString nesnesine bir işaretçidir.

Bu ince bir farktır. Derleyici uyarısı setObject:forKey:aşağıdaki gibi bildirildiği için gerçekleşir :

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

defaultNameArgümanın tipte olmasını bekliyor NSString *. Bunun yerine bir sabite işaretçi verdiğinizde, ona farklı bir şey vermiş olursunuz.

Güncelleme: Bu sabitlerinstaticsadece tek bir dosyadan kullanılacakmışgibi tanımlanması gerektiğini belirtmek isterim. Bunu söylüyorum çünkü bu problemle kendim karşılaştım: eğer onları statik olarak ilan etmezseniz, o zaman global isim alanında var olacaklar ve aynı isimde bir değişkeni başka bir dosyada kullanamayacaksınız. Daha fazla bilgi içinbkz . Objective-C'de Sabitler . Örnekle açıklamak gerekirse, şu anda yalnızca tek bir.mdosyadakullanmam gereken anahtarlar için kullandığım şey bu:

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

1
NSString * const fooçalışır çünkü NSStringdeğişmezdir ve işaretçi değişmezdir, böylece asla doğru şekilde değiştirilemez? Ayrıca, constdolaylı olarak static(bir derleyici optimizasyonu) olan C ++ 'dan hatırlıyorum, bu yüzden onu çağırmaya gerek yok. Bu burada da doğru mu?
Üç

32

Kullanmayın constObjective-C nesnelerle, onlar gerçekten kullanmak için tasarlanmamıştır. NSStringnesneler (diğerleri arasında), tasarımları nedeniyle zaten varsayılan olarak değişmezdir, bu nedenleconst yapmak işe yaramaz.

Gibi e.James önerdi , bir kullanabilirsiniz NSString * constbir sabit bir göstericisi olan NSString. Bu, bir sabiti gösteren bir gösterici olan a'dan const NSString *(eşdeğer NSString const *) ince bir şekilde farklıdır NSString. A kullanmak, yeni bir nesneyi işaret etmek için NSString * constyeniden atamanızı engeller .kPolyNSString


Const kullanımı hakkında iyi bir nokta. Bu nedenle birçok Objective-C sınıfının "Değişken" değişkenleri vardır.
James

2
Bunun constaynı zamanda onu yeniden atayamayacağın anlamına da geldiğini düşündüm . Sanırım yanılmışım.
Dan Rosenstark

18

Diğer sınıflardan erişim için:

.h

extern NSString * const PolygonNumberOfSidesPrefsKey;

.m

NSString * const PolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"

Yalnızca mevcut sınıf içinde erişim için:

.m

static NSString * const kPolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSides"

5

Hatta sabit olanı daha açıklayıcı yapmayı bile öneririm. Bir çokgenin kenar sayısı için bir sabit, herhangi bir yerden gelebilir. Bir öneri olarak:

kDefaultsPolygonNumberOfSides;

yerine.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.