【问题标题】:Clearing NSUserDefaults清除 NSUserDefaults
【发布时间】:2010-10-07 09:39:32
【问题描述】:

我使用+[NSUserDefaults standardUserDefaults] 来存储应用程序设置。这由大约十几个字符串值组成。是否可以永久删除这些值而不仅仅是将它们设置为默认值?

【问题讨论】:

标签: ios objective-c cocoa-touch nsuserdefaults


【解决方案1】:

您可以像这样删除应用程序的持久域:

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

在 Swift 3 及更高版本中:

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

这与@samvermette 的回答类似,但在 IMO 上更简洁一些。

【讨论】:

  • 这很好用,谢谢!只是不要忘记之后发布 appDomain。
  • @IcyBlueRose - bundleIdentifier 是一个自动释放的对象,因为它不以 init 或 new 开头,所以你会过度释放它。
  • 很高兴知道,谢谢!但我说的是字符串 appDomain。那辆汽车也发布了吗?
  • @IcyBlueRose bundleIdentifier返回的对象和appDomain引用的对象是一样的。
  • 我似乎无法再让它在 10.8 上运行,有人可以确认它是否有效吗?这是一个相关的 SO 问题:stackoverflow.com/questions/13595415/…
【解决方案2】:

此代码将默认值重置为注册域:

[[NSUserDefaults standardUserDefaults] setPersistentDomain:[NSDictionary dictionary] forName:[[NSBundle mainBundle] bundleIdentifier]];

换句话说,removeObjectForKey 对应于您在该应用中注册的每一个键。

感谢 Ken Thomases 在此 Apple 开发者论坛 thread.

【讨论】:

  • 非常感谢。为什么[NSUserDefaults resetStandardUserDefaults] 不这样做超出了我的理解。
  • @jboxer 我刚刚花了一些时间研究 Apple 文档,resetStandardUserDefaults 基本上将内存缓冲区刷新到磁盘并将其擦除干净。因此,下次您尝试检索一个值时,它必须从磁盘中获取它。 Core Data 的 NSManagedObjectContext 也使用了类似的“重置”术语。
  • 糟糕,我的意思是它会擦除内存缓冲区而不将其写入磁盘。因此,您在同步到磁盘之前所做的任何更改都将丢失。
  • 克里斯托弗,我认为你倒退了,尽管情况可能发生了变化。 resetStandardUserDefaults 是迄今为止我在 iOS 中看到的最容易混淆的调用。 Apple Docs 说“同步对共享用户默认对象所做的任何更改并将其从内存中释放。”所以它真的应该被称为flushAndReleaseStandardUserDefaults。我正在花时间评论一条旧评论,因为我刚刚被这个电话抓住并希望避免其他人被烧毁(我现在必须告诉客户我需要更新 90 个应用程序)。
【解决方案3】:

您是否尝试过使用 -removeObjectForKey

 [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"defunctPreference"];

【讨论】:

  • 干杯。非常感谢。
  • 有什么方法可以删除所有现有键的对象?
  • 虽然我知道这似乎可行,但为什么 defunctPreference 不是某种系统定义的常量?我肯定会担心它会在未来的某一天停止工作。
  • 之后还要同步吗?
【解决方案4】:

这是 Swift 中的答案:

let appDomain = NSBundle.mainBundle().bundleIdentifier!
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(appDomain)

【讨论】:

  • NSUserDefaults.standardUserDefaults().removePersistentDomainForName(NSBundle.mainBundle().bundleIdentifier!) one-liner
  • 或者更安全:if let domainName = NSBundle.mainBundle().bundleIdentifier { NSUserDefaults.standardUserDefaults().removePersistentDomainForName(domainName) }
  • Grace 的 oneliner Swift 4 版本:UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)
【解决方案5】:

如果你在开发过程中需要它,你也可以重置你的模拟器,删除所有NSUserDefaults

iOS 模拟器 -> 重置内容和设置...

请记住,它还会删除模拟器上的所有应用程序和文件。

【讨论】:

    【解决方案6】:
    NSDictionary *defaultsDictionary = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
    for (NSString *key in [defaultsDictionary allKeys]) {
                        [[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
    }
    

    【讨论】:

      【解决方案7】:

      在斯威夫特中:

      let defaults = NSUserDefaults.standardUserDefaults()
      defaults.dictionaryRepresentation().keys.forEach { defaults.removeObjectForKey($0) }
      

      【讨论】:

        【解决方案8】:

        我喜欢让代码更简洁的扩展:

        extension NSUserDefaults {
            func clear() {
                guard let domainName = NSBundle.mainBundle().bundleIdentifier else {
                    return
                }
        
                self.removePersistentDomainForName(domainName)
            }
        }
        

        斯威夫特 5

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

        【讨论】:

          【解决方案9】:

          注意:此答案也已针对 Swift 进行了更新。

          将它放在一条线上怎么样?

          扩展@Christopher Rogers 的答案——已被接受。

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

          是的,有时你可能需要synchronize它,

          [[NSUserDefaults standardUserDefaults] synchronize];
          

          我已经创建了一个方法来做到这一点,

          - (void) clearDefaults {
              [[NSUserDefaults standardUserDefaults] removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
              [[NSUserDefaults standardUserDefaults] synchronize];
          }
          

          斯威夫特

          使用 swift 更容易。

          extension UserDefaults {
              class func clean() {
                  guard let aValidIdentifier = Bundle.main.bundleIdentifier else { return }
                  standard.removePersistentDomain(forName: aValidIdentifier)
                  standard.synchronize()
              }
          }
          

          及用法

          UserDefaults.clean()
          

          【讨论】:

            【解决方案10】:

            我发现了这个:

            osascript -e 'tell application "iOS Simulator" to quit'
            xcrun simctl list devices | grep -v '^[-=]' | cut -d "(" -f2 | cut -d ")" -f1 | xargs -I {} xcrun simctl erase "{}"
            

            来源:https://gist.github.com/ZevEisenberg/5a172662cb576872d1ab

            【讨论】:

              【解决方案11】:

              以上所有答案都非常相关,但如果有人仍然无法重置已删除应用的用户默认设置,那么您可以重置模拟器的内容设置,它会起作用。

              【讨论】:

                【解决方案12】:

                这是一个错误或其他问题,但 removePersistentDomainForName 在清除所有 NSUserDefaults 值时不起作用。

                因此,更好的选择是重置PersistentDomain,您可以通过以下方式进行:

                NSUserDefaults.standardUserDefaults().setPersistentDomain(["":""], forName: NSBundle.mainBundle().bundleIdentifier!)
                

                【讨论】:

                  【解决方案13】:

                  扩展@folse 的答案...我相信更正确的实现将是...

                  NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
                  NSDictionary *defaultsDictionary = [[NSUserDefaults standardUserDefaults] persistentDomainForName: appDomain];
                      for (NSString *key in [defaultsDictionary allKeys]) {
                        NSLog(@"removing user pref for %@", key);
                        [[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
                      }
                  

                  ...调用 NSUserDefault 的 persistentDomainForName: 方法。正如文档所述,该方法“返回包含指定持久域中的键和值的字典”。相反,调用 dictionaryRepresentation: 将返回一个字典,该字典可能包含其他设置,因为它适用于更广泛的范围。

                  如果您需要过滤掉任何要重置的值,那么遍历键是一种方法。显然,如果您只想删除应用程序的所有首选项而不考虑,那么上面发布的其他方法之一是最有效的。

                  【讨论】:

                    【解决方案14】:

                    如果需要重置的应用程序设置是用于访问麦克风的 nsuserdefault(我的情况),一个简单的解决方案是来自 Anthony McCormick (Iphone - How to enable application access to media on the device? - ALAssetsLibraryErrorDomain Code=-3312 "Global denied access") 的回答。

                    在设备上,转到设置>常规>重置>重置位置警告

                    【讨论】:

                      【解决方案15】:

                      试试这个,它对我有用。

                      单行代码

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

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2012-03-29
                        • 2014-11-11
                        • 1970-01-01
                        • 1970-01-01
                        • 2015-06-14
                        • 1970-01-01
                        • 1970-01-01
                        • 2014-09-19
                        相关资源
                        最近更新 更多