从NSUserDefaults字典iOS中删除所有密钥


71

我使用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];

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


请参阅此相关问题,删除所有我以某个单词开头的NSUserDefaults,并获得有关使用NSPredicate在NSUserDefaults中查找某些条目的良好答案
罗勒·布尔克

Answers:


146

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

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

19
具有相同结果的最短方法:______________________________________________ NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier]; __________________ [[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
skywinder

10
这不是最佳方法,因为它将迭代并尝试删除所有用户默认键,包括系统键,而不仅仅是应用程序键。如另一个答案中所建议的那样,使用-removePersistentDomainForName:会更好。
2014年

1
使用[dict removeAllObjects]而不是遍历整个字典是否更有意义?
Fitter Man

@FitterMan不,那只会从字典中删除对象,而不是从NSUserDefaults
mxcl

71

取得与Alex Nichol最佳答案相同的结果的最短方法

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

1
如何清除NSUserDefaults alloc] initWithSuiteName。
Durgaprasad

1
synchronize如果以某种需要的方式使用默认值,请不要忘记立即使用NSUserDefaults。
艾伯特·伦肖

请注意,删除整个域时,不会通知KVO观察者(尽管会发布通知)。为了与KVO兼容,最好遍历从返回的每个键,persistentDomainForName然后使用删除它removeObjectForKey
bcause 19'Nov

44

单线:

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

synchronize如果以某种需要的方式使用默认值,请不要忘记立即使用NSUserDefaults。
艾伯特·伦肖

3
从iOS 11开始,不建议使用同步。
约翰·弗里克

29

简单的解决方案

目标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)
}

16

迅捷版:

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

1
可选的,
不解

1
是的,尽管如果使用主捆绑包,捆绑包标识符不太可能为零,但建议使用Juan的代码。
superarts.org

16

+ (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操作结束时,用户默认值的磁盘和内存副本都将不包含应用程序设置的任何值。


11

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()
uplearnedu.com 2009年

@GerardGrundy您不需要.synchronize()。在这种正常情况下,您永远不会这样做。内容将自动保存。
埃里克·艾雅

@Moritz尽管如果该应用在没有时间自动保存之前关闭,则您需要强制保存。
uplearnedu.com 17/09/21

另外,synchronize不仅仅是“保存”。synchronize保存加载整个默认对象(可能比预期的大)。无需调用synchronize即可“保存”默认值。如果调用它,则必须有充分的理由,而这些理由很少见。;)
Eric Aya

10

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

斯威夫特3:

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

当您不想依赖主捆绑包时的最佳解决方案。就我而言,我正在加载特定的捆绑软件,并且不确定是否真正删除了密钥。
哈维尔·卡拉特拉瓦·拉维里亚

5

对于Swift 3:

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


2

迅速

 func resetUserDefaults(){

    let userDefaults = NSUserDefaults.standardUserDefaults()
    let dict = userDefaults.dictionaryRepresentation() as NSDictionary

    for key in dict.allKeys {

            userDefaults.removeObjectForKey(key as! String)
    }

    userDefaults.synchronize()

}


1

此方法不这样做吗:

+ (void)resetStandardUserDefaults

从文档中NSUserDefaults

resetStandardUserDefaults

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

+ (void)resetStandardUserDefaults

讨论区

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

基于此,您可以执行以下操作:

[NSUserDefaults resetStandardUserDefaults];
[NSUserDefaults standardUserDefaults];

现在应该重置默认值。


当我调用[NSUserDefaults resetStandardUserDefaults]时;它不会删除任何内容。
Tono Nam

据我了解,这与standardUserDefaults共享对象有关,而不是与存储在磁盘上的信息有关,这意味着这对保存的用户默认值没有明显影响。
Alex Nichol

1
@Tono:当你打电话[NSUserDefaults resetStandardUserDefaults];,并随后NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];,我的理解(这可能是不正确的)是prefs将一张白纸一次。
PengOne

@Alex:是的,这是相同的想法。自从我从事有关我的讨论以来,我还没有阅读您的答案。我将删除该编辑内容,并采用这种方法。
PengOne

1

Swift 3或4 我们甚至可以将描述的片段简化为以下现代表达形式:

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

0

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

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

0

我发现将代码放在的扩展名中最方便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()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.