【问题标题】:Delete all keys from a NSUserDefaults dictionary iOS从 NSUserDefaults 字典 iOS 中删除所有键
【发布时间】:2011-10-11 10:39:57
【问题描述】:

我使用 NSUserDefaults 字典来存储基本信息,例如高分等,这样当用户关闭应用程序时数据就不会丢失。反正我用:

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];

存储数据。例如,如果我想存储一个新的高分,那么我会这样做:

[prefs setInteger:1023 forKey:@"highScore"];
[prefs synchronize];  //this is needed in case the app is closed. 

以后如果我想找回高分,我会这样做:

[prefs integerForKey:@"highScore"];

无论如何,关键是我存储了很多其他东西,因为 NSUserDefaults enable 你要存储 booleansintegersobjects 等。我必须执行什么方法来删除所有键,以便 NSUserDefaults就像我第一次启动应用程序一样?

我正在寻找类似的东西:

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs deleteAllKeysAndObjectsInTheDictionary];

或者也许有一种获取所有键的方法,我必须遍历每个对象,但我不知道如何删除它们。

编辑:

我试过了:

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[NSUserDefaults resetStandardUserDefaults];
[prefs synchronize];

而且我仍然能够获得高分....

【问题讨论】:

标签: ios objective-c swift cocoa-touch nsuserdefaults


【解决方案1】:

如果您查看NSUserDefaults documentation,您将看到一个方法- (NSDictionary *) dictionaryRepresentation。在标准用户默认值上使用此方法,您可以获得用户默认值中所有键的列表。然后,您可以使用它来清除用户默认值:

- (void)resetDefaults {
    NSUserDefaults * defs = [NSUserDefaults standardUserDefaults];
    NSDictionary * dict = [defs dictionaryRepresentation];
    for (id key in dict) {
        [defs removeObjectForKey:key];
    }
    [defs synchronize];
}

【讨论】:

  • 获得相同结果的最短方法:______________________________________________NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];__________________[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
  • 这不是最好的方法,因为它会迭代并尝试删除 all 用户默认键,包括系统键,而不仅仅是应用程序键。使用 -removePersistentDomainForName: 如另一个答案中的建议要好得多。
  • 使用 [dict removeAllObjects] 而不是遍历整个字典不是更有意义吗?
  • @FitterMan 不,这只会从字典中删除对象,而不是从 NSUserDefaults...
【解决方案2】:

获得相同结果的最短方法,如 Alex Nichol 的最佳答案:

NSString *appDomain = NSBundle.mainBundle.bundleIdentifier;
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
[[NSUserDefaults standardUserDefaults] synchronize];

【讨论】:

  • 如何清除 NSUserDefaults alloc]initWithSuiteName.
  • 不要忘记synchronize你的NSUserDefaults,如果你以某种方式使用默认值。
  • 请注意,删除完整域时不会通知 KVO 观察者(尽管会发布通知)。对于 KVO 兼容性,最好遍历从 persistentDomainForName 返回的每个键并使用 removeObjectForKey 将其删除。
【解决方案3】:

单线:

[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:NSBundle.mainBundle.bundleIdentifier];

【讨论】:

  • 不要忘记synchronize您的 NSUserDefaults 如果您以需要的方式使用默认值。
  • 从 iOS 11 开始,同步已被弃用。
【解决方案4】:

简单的解决方案

目标 C:

NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];

Swift 3.0 到 Swift 5.0:

if let appDomain = Bundle.main.bundleIdentifier {
    UserDefaults.standard.removePersistentDomain(forName: appDomain)
}

【讨论】:

    【解决方案5】:

    Swift 版本:

    if let bid = NSBundle.mainBundle().bundleIdentifier {
        NSUserDefaults.standardUserDefaults().removePersistentDomainForName(bid)
    }   
    

    【讨论】:

    • 可选未解包,不遵守 Swift 最佳实践
    • 是的,虽然如果你使用主包,包标识符不太可能为零,但建议使用胡安的代码。
    【解决方案6】:

    + (void) resetStandardUserDefaults 不会保留更改,它只是重置内存中的用户默认对象,以便下一次 synchronize 调用将从磁盘副本中读取,而不是使用磁盘版本。

    遍历键更好,但实际上有一个函数可以为您执行此操作:removePersistentDomainForName:

    // you can usually get the domain via [[NSBundle mainBundle] bundleIdentifier]
    [[NSUserDefaults standardUserDefaults]
     removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
    // or use a string for any other settings domains you use
    //[[NSUserDefaults standardUserDefaults]
    // removePersistentDomainForName:@"com.mycompany.myappname"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    

    synchronize 操作结束时,用户默认值的磁盘和内存副本将不包含您的应用程序设置的任何值。

    【讨论】:

      【解决方案7】:

      Swift 中的 Oneliner:

      斯威夫特 3

      NSUserDefaults.standardUserDefaults().removePersistentDomainForName(
      NSBundle.mainBundle().bundleIdentifier!)
      

      斯威夫特 4

      UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)
      

      【讨论】:

      • Swift 4.0 ----- UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!) UserDefaults.standard.synchronize()
      • @GerardGrundy 你不需要.synchronize()。在这种正常情况下,您永远不会这样做。内容会自动保存。
      • @Moritz 虽然如果应用程序在有时间自动保存之前关闭,那么您需要强制保存。
      • 另外,synchronize 不仅仅是“保存”。 synchronize 保存 加载整个默认对象(可能比预期的大)。永远不需要调用synchronize 来“保存”默认值。如果你叫它,你一定有充分的理由,而且这些是很少见的。 ;)
      【解决方案8】:

      对于那些想要在测试目标中执行此操作的人,请使用它(因为 removePersistentDomain 不适用于这种情况)

      斯威夫特 3:

      for key in Array(UserDefaults.standard.dictionaryRepresentation().keys) {
           UserDefaults.standard.removeObject(forKey: key)
      }
      

      【讨论】:

      • 不想依赖主包时的最佳解决方案。在我的情况下,我正在加载一个特定的包,我不确定键是否真的被删除了。
      【解决方案9】:

      对于 Swift 3:

      let appDomain = Bundle.main.bundleIdentifier!
      UserDefaults.standard.removePersistentDomain(forName: appDomain)
      

      【讨论】:

        【解决方案10】:

        对于 Swift 3:

        if let bundle = Bundle.main.bundleIdentifier {
            UserDefaults.standard.removePersistentDomain(forName: bundle)
        }
        

        【讨论】:

          【解决方案11】:

          Swift
          放在你的逻辑中

          if let appDomain = Bundle.main.bundleIdentifier {
            UserDefaults.standard.removePersistentDomain(forName: appDomain)
          }
          

          【讨论】:

            【解决方案12】:

            斯威夫特

            func resetUserDefaults(){
              let userDefaults = NSUserDefaults.standardUserDefaults()
              let dict = userDefaults.dictionaryRepresentation() as NSDictionary
                    
              for key in dict.allKeys {
                userDefaults.removeObjectForKey(key as! String)
              }
                    
              userDefaults.synchronize()      
            }
            

            【讨论】:

              【解决方案13】:

              这个方法不这样做吗:

              + (void)resetStandardUserDefaults
              

              来自NSUserDefaults的文档:

              resetStandardUserDefaults

              同步对共享用户默认对象所做的任何更改,并 从内存中释放它。

              + (void)resetStandardUserDefaults

              讨论

              随后调用 standardUserDefaults 创建一个新的共享 用户使用标准搜索列表默认对象。

              基于此,你可以这样做:

              [NSUserDefaults resetStandardUserDefaults];
              [NSUserDefaults standardUserDefaults];
              

              现在应该重置默认值。

              【讨论】:

              • 当我调用 [NSUserDefaults resetStandardUserDefaults];它不会删除任何东西。
              • 据我了解,这与标准用户默认值共享对象有关,而不是与存储在磁盘上的信息有关,这意味着这对保存的用户默认值没有明显影响。
              • @Tono:当你打电话给[NSUserDefaults resetStandardUserDefaults];thenNSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 时,我的理解(可能不正确)是prefs 将是一次空白再次。
              • @Alex:是的,这是同一个想法。由于我正在讨论我的问题,因此我还没有阅读您的答案。我将删除编辑并按照您的方式处理。
              【解决方案14】:

              Swift 3 或 4 我们甚至可以将描述的 sn-p 简化为这个现代表达式:

              func clearAll() {
                  let settingsDictionary = userDefaults.dictionaryRepresentation()
                  settingsDictionary.forEach { key, _ in userDefaults.removeObject(forKey: key) }
                  userDefaults.synchronize()
              }
              

              【讨论】:

                【解决方案15】:

                我发现将代码放在UserDefaults 的扩展中最方便。

                斯威夫特 5

                extension UserDefaults {
                    static func clear() {
                        guard let domain = Bundle.main.bundleIdentifier else { return }
                        UserDefaults.standard.removePersistentDomain(forName: domain)
                        UserDefaults.standard.synchronize()
                    }
                }
                

                用法

                UserDefaults.clear()
                

                【讨论】:

                  【解决方案16】:

                  快速删除所有 UserDefault 值(最新语法)

                  //remove UserDefaults
                  if let identifier = Bundle.main.bundleIdentifier {
                    UserDefaults.standard.removePersistentDomain(forName: identifier)
                    UserDefaults.standard.synchronize()
                  }
                  

                  【讨论】:

                    【解决方案17】:

                    在 Swift 5.0 以下单行代码就足够了。

                    UserDefaults.standard.dictionaryRepresentation().keys.forEach(defaults.removeObject(forKey:))
                    

                    【讨论】:

                      【解决方案18】:

                      我用这个:

                      UserDefaults.standard.removeAll()
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 2012-09-05
                        • 2012-03-18
                        • 1970-01-01
                        • 1970-01-01
                        • 2017-03-08
                        • 1970-01-01
                        相关资源
                        最近更新 更多