NSUserDefaults - Как определить, существует ли ключ

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

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

Несколько примеров: Приложение запускается, если оно запускается впервые, выдает предупреждение "Добро пожаловать". Чтобы узнать, открылся ли он впервые, он читает UserDefaults и проверяет.

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

Некоторая помощь здесь? Я действительно ценю это!

Ответ 1

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

Ответ 2

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

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

    NSLog(@"mykey found");
}

Ответ 3

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

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

Ответ 4

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

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

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

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

Ответ 5

Попробуйте этот маленький crumpet:

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

Рассматривайте все как объект. Кажется, работает для меня.

Ответ 6

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

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

Ответ 7

Свифт 3/4:

Вот простое расширение для типов ключей-значений Int/Double/Float/Bool, которые имитируют поведение Optional-return других типов, доступных через 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 (строка, данные и т.д.). Просто используйте методы 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

Ответ 8

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

extension UserDefaults {

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

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

Ответ 9

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

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

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

//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"]) {
 ...

Это, похоже, работает в моем случае. Это просто показало мне больше смысла.

Ответ 11

Swift 3.0

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