NSUserDefaults - 如何判断密钥是否存在

Eth*_*ick 203 iphone objective-c nsuserdefaults ios

我正在开发一个小型iPhone应用程序,我正在使用NSUserDefaults我的数据持久性.它只需跟踪一些事情,例如一些名字和一些数字,所以我想我也可以保持简单.

我找到了这个页面作为参考,但我不认为它可以回答我的问题.基本上,我希望能够检查一个值(或一个键)是否已经存在NSUserDefaults,然后相应地做一些事情.

一些例子:应用程序启动,如果这是第一次启动它会输出一个表示欢迎的警报.要判断这是否是第一次打开,它会读取UserDefaults并检查.

示例2:它表示"Hello [Name]",其中Name是您输入的内容.如果你打开了应用程序并且没有名字,那就应该说"Hello World".我需要检查您是否已经输入了名称并采取相应措施.该名称将存储在NSUserDefaults.

有些帮助吗?我真的很感激!

jsp*_*cal 377

objectForKey:nil如果它不存在将返回.

  • 是的,它甚至适用于原始数据类型,如BOOL. (47认同)
  • @zekel而不是猜测,我测试了这个(在iOS 5.1.1上),它肯定检测到BOOL是否存在,与BOOL的值可能无关.当BOOL不存在时,"objectForKey"返回nil,因为它从未被设置过. (40认同)
  • Apple的文档说"如果布尔值与用户默认值中的defaultName相关联,则返回该值.否则,返回NO." 我不认为上面的答案对于BOOL是正确的,你无法确定它是否定义为NO或不存在.我想你必须使用` - dictionaryRepresentation`并检查密钥. (12认同)
  • 如果你有一个BOOL并用boolForKey测试它,那么@zekel是对的,你得到YES或NOT.如果你使用objectForKey进行测试(如答案所示),如果没有设置密钥,你会得到nil. (8认同)
  • 这是否适用于原始数据类型? (7认同)
  • 我第三个概念,我刚刚测试了这个,它可以判断对象是否存在,即使它是一个设置为 NO 的 BOOL。 (3认同)
  • 同意,根据我的测试,这个答案是正确的 (2认同)
  • 至少从iOS 6.1模拟器开始,这不再起作用.如果objectForKey不存在,则返回相同的值,如果BOOL为NO,则返回相同的值.i.jameelkhan的解决方案确实有效 (2认同)

i.j*_*han 94

如上所述,它不适用于原始类型,其中0/NO可能是有效值.我正在使用此代码.

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

    NSLog(@"mykey found");
}
Run Code Online (Sandbox Code Playgroud)


mir*_*rap 54

如果值不存在,objectForKey:则返回该方法nil.这是一个简单的IF/THEN测试,它会告诉你值是否为零:

if([[NSUserDefaults standardUserDefaults] objectForKey:@"YOUR_KEY"] != nil) {
    ...
}
Run Code Online (Sandbox Code Playgroud)


小智 6

" 如果objectForKey不存在,它将返回nil . "如果它确实存在,它也将返回nil,它是一个整数或一个值为零的布尔值(即布尔值为FALSE或NO).

我已经在5.1和6.1的模拟器中对此进行了测试.这意味着您无法通过询问"对象"来测试已设置的整数或布尔值.如果您不介意将"未设置"视为"设置为零",那么您可以为整数逃脱.

已经测试过这个的人似乎已被假阴性方面所欺骗,即通过查看objectForKey是否在您知道密钥尚未设置时返回nil进行测试,但未注意到如果密钥已经设置它也返回nil设置但已设置为NO.

对于我自己的问题,那个发送给我的人,我最后改变了我的布尔语义,以便我所希望的默认值与值设置为NO一致.如果这不是一个选项,你需要存储一个布尔值以外的东西,并确保你可以区分YES,NO和"not set".

  • 有点晚了,但为了新手的利益:这是不正确的。整数的 UserDefault 值设置为 0 和 Bools 设置为 false 上的 object(forKey) 将正确返回非 nil。如果您使用 bool(forKey) 来测试是否设置了某个值,您可能会遇到问题(因为如果该值设置为 False,则 bool(forKey) 将返回 'false',即使您期望的是 'true'。) (2认同)

ste*_*tef 6

斯威夫特 3 / 4:

这是 Int/Double/Float/Bool 键值类型的一个简单扩展,它模仿了通过 UserDefaults 访问的其他类型的 Optional-return 行为。

编辑 2018 年 8 月 30 日:根据 Leo 的建议使用更有效的语法进行了更新。)

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
    }
}
Run Code Online (Sandbox Code Playgroud)

它们现在与其他内置 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
Run Code Online (Sandbox Code Playgroud)

  • 我更喜欢`return self.object(forKey: key) as? Int` 以便仅搜索一次值。 (2认同)

mbe*_*sky 5

扩展UserDefaults一次,不要复制粘贴此解决方案:

extension UserDefaults {

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

// Example
UserDefaults.standard.hasValue(forKey: "username")
Run Code Online (Sandbox Code Playgroud)