NSUserDefaults - Bir anahtarın var olup olmadığını belirleme


208

Küçük bir iPhone uygulaması üzerinde çalışıyorum ve NSUserDefaultsveri kalıcılığım olarak kullanıyorum . Bazı isimler ve bazı rakamlar gibi sadece birkaç şeyi takip etmek zorundadır, bu yüzden basit tutabileceğimi düşünüyorum.

Bu sayfayı referans olarak buldum , ancak soruma cevap verebileceğini düşünmüyorum. Temel olarak, zaten bir değerin (veya bir anahtarın) var olup olmadığını kontrol etmek NSUserDefaultsve sonra buna göre bir şey yapmak istiyorum.

Bazı örnekler: Uygulama başlatılır, eğer ilk kez başlatılırsa hoş geldiniz diyerek bir uyarı verir. Bunu ilk açıp açmadığını söylemek için okur UserDefaultsve kontrol eder.

Örnek 2: Adın girdiğiniz bir şey olduğu "Merhaba [Ad]" yazıyor. Uygulamayı açtıysanız ve bir ad yoksa, "Merhaba Dünya" yazmalıdır. Zaten bir ad girip girmediğinizi kontrol etmem ve buna göre hareket etmem gerekiyor. İsim içinde saklanır NSUserDefaults.

Burada yardıma ihtiyacın var mı? Gerçekten minnettar olurum!

Yanıtlar:


382

objectForKey:yoksa geri dönecektir nil.


1
İlkel bir veri türünü NSUserDefaults'ta depolayabileceğinizi sanmıyorum.
kender

12
Apple'ın belgeleri "Kullanıcı varsayılanlarında bir Boole değeri defaultName ile ilişkilendirilirse, bu değer döndürülür. Aksi takdirde NO döndürülür." Yukarıdaki cevabın BOOL'lar için doğru olduğunu düşünmüyorum, HAYIR olarak tanımlanıp tanımlanmadığını tespit edemezsiniz. – dictionaryRepresentationAnahtarı kullanmanız ve kontrol etmeniz gerektiğini düşünüyorum .
zekel

40
@zekel Tahmin etmek yerine bunu (iOS 5.1.1'de) test ettim ve söz konusu BOOL değerinin ne olabileceğinden bağımsız olarak bir BOOL'un olup olmadığını kesinlikle tespit etti. "objectForKey", BOOL mevcut olmadığında hiç ayarlanmadığı için sıfır döndürdü.
DataGraham

8
Bir BOOL'ınız varsa ve boolForKey ile test ederseniz, @zekel doğrudur, EVET veya DEĞİL alırsınız. ObjectForKey ile test ederseniz (cevabın önerdiği gibi), anahtar ayarlanmamışsa nil alırsınız.
Giuseppe Garassino

2
Bu artık en azından iOS 6.1 Simulator'dan itibaren çalışmıyor. objectForKey, yoksa ve NO BOOL ile mevcutsa aynı değeri döndürür. i.jameelkhan'ın çözümü işe yarıyor
lschult2

98

Yukarıda belirtildiği gibi, 0 / NO'nun geçerli bir değer olabileceği ilkel tipler için çalışmaz. Bu kodu kullanıyorum.

NSUserDefaults *defaults= [NSUserDefaults standardUserDefaults];
if([[[defaults dictionaryRepresentation] allKeys] containsObject:@"mykey"]){

    NSLog(@"mykey found");
}

Bu beni kurtardı. Teşekkürler!
BalestraPatrick

Bu gibi ilkellerle uğraşırken doğru cevap budur BOOL. Bunun NOaksine, ayarlanmamış ve ayarlanmamıştır objectForKey:.
devios1

@ devios1 - Anahtar eksikse, programcının sonunda bir veya başka bir veri türünü saklama amacına bakılmaksızın objectForKey:geri döner . Bir ilkel varsa, anahtar ilkel bir değerle ilişkilendirilse bile geri dönmez . nilBoolobjectForKey:nil
Ted Hopp

Bu doğru cevap: Açıkçası, objectForKey 0'ı nil ile karıştırdığı için kabul edilen cevap yanlış, bu yüzden işe yaramaz.
İOS 4.3'ten 10.2.1'e

Bu eski olduğunu biliyorum, ama şimdi sadece bu bilgiye ihtiyaç duyduktan sonra, 'includeObject:' referans sadece şu anlama gelir: nesne. Anahtar değil. IOW, başlık dosyanızda şu tanımladıysanız: #define kMyKey @ "myKey" "includeObject", "kMyKey" i aramıyor, "myKey" i arıyor. 'KMyKey' kullanılması her zaman 'NO' döndürür.
Bill Norman

55

objectForKey:Yöntem dönecektir nildeğeri yoksa. İşte değerin sıfır olup olmadığını söyleyecek basit bir IF / THEN testi:

if([[NSUserDefaults standardUserDefaults] objectForKey:@"YOUR_KEY"] != nil) {
    ...
}

6

" objectForKey yoksa nil döndürür. " Varsa da nil döndürür ve sıfır değerine sahip bir tamsayı veya boole (yani boole için FALSE veya NO).

Bunu simülatörde 5.1 ve 6.1 için test ettim. Bu, "nesne" isteyerek ayarlanmış tam sayıları veya booleları gerçekten test edemeyeceğiniz anlamına gelir. Eğer "ayarlanmadı" gibi "sıfıra ayarlanmış" gibi davranmak sakıncası yoksa tamsayılar için bu kurtulmak.

Bunu daha önce test eden kişiler yanlış negatif yön tarafından aldatılmış gibi görünüyor, yani anahtarın ayarlanmadığını bildiğinizde objectForKey'nin nil döndürüp döndürmediğini ancak anahtar ayarlanmışsa nil döndürdüğünü fark edemediğini test ederek ayarlandı ancak NO olarak ayarlandı.

Beni buraya gönderen kendi sorunum için, booleanımın anlambilimini değiştirdim, böylece istenen varsayılan değer NO değerine ayarlanmıştı. Bu bir seçenek değilse, bir boole dışında bir şey olarak depolamanız ve EVET, HAYIR ve "ayarlanmadı" arasındaki farkı söyleyebilmeniz gerekir.


Bunu doğruladım, ama kolay bir çözüm var; yalnızca yeni nesne değişmezlerini veya kutulu bir ifadeyi kullanın. @0yerine 0, @NOyerine NOveya basitçe @(variable). Bunları burada okuyun.
kaka

1
Biraz geç, ama yeni başlayanların yararı için: bu yanlış. 0'a ve tamsayı false olarak ayarlanmış tamsayıların UserDefault değerlerindeki nesne (forKey), nil olmayan değeri doğru olarak döndürür. Bir değerin ayarlanıp ayarlanmadığını test etmek için bool (forKey) kullanırsanız, sorun yaşayabilirsiniz (çünkü değer False olarak ayarlanmışsa, bool (forKey), 'true' bekliyorsanız bile 'false' döndürür.)
thecloud_of_unknowing

5

Hızlı 3/4:

Burada, UserDefaults aracılığıyla erişilen diğer türlerin İsteğe bağlı dönüş davranışını taklit eden Int / Double / Float / Bool anahtar / değer çiftleri için basit bir uzantıdır.

( 30 Ağustos 2018'de düzenle: Leo'nun önerisinden daha verimli sözdizimi ile güncellendi.)

extension UserDefaults {
    /// Convenience method to wrap the built-in .integer(forKey:) method in an optional returning nil if the key doesn't exist.
    func integerOptional(forKey: String) -> Int? {
        return self.object(forKey: forKey) as? Int
    }
    /// Convenience method to wrap the built-in .double(forKey:) method in an optional returning nil if the key doesn't exist.
    func doubleOptional(forKey: String) -> Double? {
        return self.object(forKey: forKey) as? Double
    }
    /// Convenience method to wrap the built-in .float(forKey:) method in an optional returning nil if the key doesn't exist.
    func floatOptional(forKey: String) -> Float? {
        return self.object(forKey: forKey) as? Float
    }
    /// Convenience method to wrap the built-in .bool(forKey:) method in an optional returning nil if the key doesn't exist.
    func boolOptional(forKey: String) -> Bool? {
        return self.object(forKey: forKey) as? Bool
    }
}

Artık diğer yerleşik alma yöntemleriyle (dize, veri vb.) Daha uyumludurlar. Sadece eskilerinin yerine get yöntemlerini kullanın.

let AppDefaults = UserDefaults.standard

// assuming the key "Test" does not exist...

// old:
print(AppDefaults.integer(forKey: "Test")) // == 0
// new:
print(AppDefaults.integerOptional(forKey: "Test")) // == nil

2
return self.object(forKey: key) as? IntSadece bir kez değer aramak için tercih ederim .
Leo

3

Sadece bunun üzerinden geçtim ve tüm cevaplarınız benim için iyi bir çözüme yardımcı oldu. Sadece okumak ve anlamakta zorlandığım için önerilen rotayı izlemeye direndim.

İşte yaptığım şey. Ben "_talkative" adlı bir değişken taşınan bir BOOL vardı.

Benim varsayılan (NSUserDefaults) nesnesini ayarladığınızda , daha sonra nil olup olmadığını görmek için test gibi bir nesne olarak ayarlayın :

//converting BOOL to an object so we can check on nil
[defaults setObject:@(_talkative) forKey:@"talkative"];

Sonra var olup olmadığını görmek için gittiğimde, kullandım:

if ([defaults objectForKey:@"talkative"]!=nil )
  {

Sonra nesneyi BOOL olarak kullandım:

if ([defaults boolForKey:@"talkative"]) {
 ...

Benim durumumda bu işe yarıyor gibi görünüyor. Benim için daha görsel bir anlam ifade etti.


Bu benim için çalıştı ([varsayılan boolForKey: @ "konuşkan"]
Vineesh TP

3

Bu küçük parça deneyin:

-(void)saveUserSettings{
NSNumber*   value;

value = [NSNumber numberWithFloat:self.sensativity];
[[NSUserDefaults standardUserDefaults] setObject:value forKey:@"sensativity"];
}
-(void)loadUserSettings{
    NSNumber*   value;
    value = [[NSUserDefaults standardUserDefaults] objectForKey:@"sensativity"];
    if(value == nil){
        self.sensativity = 4.0;
    }else{
        self.sensativity = [value floatValue];
    }
}

Her şeye bir nesne gibi davran. Benim için iş gibi görünüyor.


3

Almak için hızlı sürüm Bool?

NSUserDefaults.standardUserDefaults().objectForKey(DefaultsIsGiver) as? Bool

1
Neden kullanmıyorsunuz boolForKey? NSUserDefaults.standardUserDefaults().boolForKey(DefaultsIsGiver)
JAL

1
boolForKeydönecek Boolve dönmeyecek Bool?, bu yüzden anahtar orada değilse alacaksınız falseve değilnil
Ben

3

UserDefaultsBu çözümü kopyalayıp yapıştırmamak için bir kez uzatın :

extension UserDefaults {

    func hasValue(forKey key: String) -> Bool {
        return nil != object(forKey: key)
    }
}

// Example
UserDefaults.standard.hasValue(forKey: "username")

0

Swift3'te bu şekilde kullandım

var hasAddedGeofencesAtleastOnce: Bool {
    get {
        return UserDefaults.standard.object(forKey: "hasAddedGeofencesAtleastOnce") != nil
    }
}

Cevap o birden çok kez kullanmak istiyorsak harika.

Umut ediyorum bu yardım eder :)


-1

Swift 3.0

if NSUserDefaults.standardUserDefaults().dictionaryRepresentation().contains({ $0.0 == "Your_Comparison_Key" }){
                    result = NSUserDefaults.standardUserDefaults().objectForKey(self.ticketDetail.ticket_id) as! String
                }
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.