NSUserDefaults - как узнать, существует ли ключ

Я работаю над небольшим приложением для iPhone, и я использую NSUserDefaults как моя настойчивость данных. Он должен отслеживать только некоторые вещи, такие как некоторые имена и некоторые цифры, поэтому я думаю, что я мог бы также держать его простым.

нашел на этой странице для справки, но я не думаю, что он может ответить на мой вопрос. В принципе, я хочу иметь возможность проверить, существует ли значение (или ключ) уже в NSUserDefaults а затем сделайте что-нибудь соответственно.

некоторые примеры: приложение запускается, если это первый раз, когда он запускается, он выводит предупреждение о приветствии. Чтобы сказать, если это первый раз, когда он открыл его, он читает UserDefaults и проверяет.

Пример 2: он говорит: "Привет [имя]", где имя-это то, что вы вступили. Если вы открыли приложение и нет никакого имени, он должен сказать "Здравствуй, Мир.- Мне нужно проверить, ввели ли вы уже имя, и действовать соответственно. Имя будет сохранено в NSUserDefaults.

какая-то помощь здесь? Я бы очень ценю это!

11 ответов


objectForKey: вернутся nil если он не существует.


Как упоминалось выше, он не будет работать для примитивных типов, где 0 / NO может быть допустимым значением. Я использую этот код.

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

    NSLog(@"mykey found");
}

на objectForKey: метод возвращает nil если значение не существует. Вот простой тест IF / THEN, который скажет вам, если значение равно nil:

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

"objectForKey вернет ноль, если он не существует. " Он также вернет nil, если он существует, и он является целым числом или булевым со значением нуля (т. е. FALSE или NO для булева).

Я тестировал это в симуляторе как для 5.1, так и для 6.1. Это означает, что вы не можете проверить, были ли заданы целые числа или логические значения, запросив "объект". Вы можете уйти с этим для целых чисел, если вы не против лечения "не установлено", как если бы это было "в ноль".

люди, которые уже протестировали это, похоже, были обмануты ложным отрицательным аспектом, т. е. проверяя это, увидев, возвращает ли objectForKey nil, когда вы знаете, что ключ не был установлен, но не замечая, что он также возвращает nil, если ключ был установлен, но был установлен в NO.

для моей собственной проблемы, которая отправила меня сюда, я просто изменил семантику моего boolean так, чтобы мое желаемое значение по умолчанию соответствовало значению NO. Если это не вариант, вам нужно сохранить как что-то другое, кроме логического, и убедиться, что вы можете сказать разницу между "Да", " нет " и "не установлено"."


попробуйте эту маленькую лепешку:

-(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];
    }
}

рассматривать все как объект. Похоже, это работает на меня.


Swift версия, чтобы получить Bool?

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

расширения UserDefaults один раз, чтобы не копировать-вставить это решение:

extension UserDefaults {

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

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

Я только что прошел через это, и все из ваших ответов помогли мне к хорошему решению, для меня. Я отказывался следовать предложенному маршруту только потому, что мне было трудно читать и понимать.

вот что я сделал. У меня был BOOL, который носился в переменной под названием "_talkative".

когда я устанавливаю свой объект по умолчанию (NSUserDefaults), я устанавливаю его как объект как я мог тогда проверить, было ли это шь:

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

затем, когда я пошел посмотреть, существует ли он, я использовал:

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

затем я использовал объект как BOOL:

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

Это, кажется, работает в моем случае. Просто для меня это имело больше визуального смысла.


Swift 3 / 4:

вот простое расширение для типов ключей int/Double/Float / Bool, которые имитируют необязательное поведение возврата других типов, доступных через UserDefaults.

(Редактировать 30 Авг 2018: обновлено с более эффективным синтаксисом из предложения Лео.)

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
    }
}

теперь они более согласованы с другими встроенными методами get (string, data и т. д.). Просто используйте методы get вместо старого те.

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

в Swift3 я использовал таким образом

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

на ответ отлично, если вы должны использовать это несколько раз.

надеюсь, это поможет:)


Swift 3.0

if NSUserDefaults.standardUserDefaults().dictionaryRepresentation().contains({ .0 == "Your_Comparison_Key" }){
                    result = NSUserDefaults.standardUserDefaults().objectForKey(self.ticketDetail.ticket_id) as! String
                }