模拟器上卸载应用后,NSUserDefaults没有被清除

98

这可能听起来很菜鸟!我想检查用户是否第二次进入我的应用程序,为了保持运行计数,我正在使用NSUserDefaults。 我在rootViewControllerviewDidLoad方法中实现了以下代码:

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

    NSLog(@"hello %ld", (long)[userDefaults integerForKey:@"runCount"]);

    if ([userDefaults integerForKey:@"runCount"] != 1) {
        //not the 2nd run
        [userDefaults setInteger:1 forKey:@"runCount"];
        NSLog(@"not 2nd run");
    } else {
        //second run or more
        NSLog(@"2nd run");
    }

    [userDefaults synchronize];

一切都运行良好,但问题在于当我根据这里这里的指示卸载(删除并重新安装)应用程序时,数据应该被清除,但实际上未被清除,重新安装应用程序后先前的数据仍然显示。


2
你尝试在实际设备上测试过吗? - Henry F
你需要在模拟器上手动清除它。这里是方法 - Sergey Kalinichenko
请标记正确答案,使此问题不再未回答。 - anders
1
@Reza:[[NSUserDefaults standardUserDefaults]setObject:selectedLists forKey:UserID]。我的应用程序在iOS8中崩溃,尽管在iOS6和iOS7中运行良好。这里的selectedLists是NSMutable Array,UserID是一个字符串。 - Manthan
@Manthan 这是一个不同的问题,但我在其他地方也遇到了同样的问题,导致崩溃的原因是,尽管我为某个键保存的对象是 NSMutableArray,但它被保存为 NSArray,更改它会导致我的应用程序崩溃... 我建议保存一个 NSArray,当您想要稍后使用它时,使用 [NSMutableArray arrayWithArray:array]; 将其转换为 NSMutableArray。希望这可以帮助到你。 - Reza Shayestehpour
7个回答

173

我认为这是iOS8 Beta模拟器中的一个错误。

预期行为是,当应用程序被删除时,该应用程序的NSUserDefaults也会被删除。

  • 但是,在从模拟器中删除应用程序时,并没有删除NSUserDefaults。
  • 在运行iOS8的实际设备上删除它们时,它们会被正确地删除。

现在的一个快速而烦人的解决方法是点击“iOS模拟器”->“重置内容和设置”。

Xcode 9.2与Simulator 10仍存在此问题。菜单选项现在为“硬件..擦除所有内容和设置”

顺便说一句,我提交了一个错误报告


45
我在iOS 8 GM上测试过了,这个漏洞仍然存在。非常烦人。 - Manfred Scheiner
1
我也可以确认在Xcode 6 GM模拟器和iOS 8 (12A365)中存在这种错误行为! - Boris Brdarić
1
现有的Open Radar链接,供想要跟进此案件的人使用:http://openradar.appspot.com/18540702 - viggio24
1
看起来在更新到XCode 6.1(6A1052d)后,SDK 8.1上的错误已经修复了。 - kas-kad
2
对于遇到相同问题的人。如果您在同一组下有多个应用程序,并且它们都使用应用程序组(在功能下为ON),则必须从设备中删除所有应用程序,以便清除用户默认值。由于用户默认值是共享的,即使设备上有一个应用程序,它也不会被删除,因为该应用程序将使用用户默认值。 - Ankit Srivastava
显示剩余9条评论

14

由于重置内容和设置是一种核心选项,因此在解决iOS 8 / Xcode 6 GM模拟器上的错误之前,您可以考虑另外两个选项:

  1. 您可以手动删除存储 NSUserDefaults 的plist文件。 它当前位于 〜/ Library / Developer / CoreSimulator / Devices / * some_device_id * / Library / Preferences / com.yourcompany.yourapp.plist 。 在UUID目录名称中找到适当的模拟器有点繁琐。编辑:2014-10-28 20-34-52 正确路径: ~/Library/Developer/CoreSimulator/Devices/*some_device_id*/data/Library/Preferences/com.yourcompany.yourapp.plist

  2. 您可以对该 plist 进行“手术”(也许使用运行脚本构建阶段),使用 plistbuddy ,例如:

/usr/libexec/plistbuddy -c "Set :BSDidMoveSqliteDb 0" path_to_plist


在/some_device_id/后面缺少/data/。 - The dude

8

对于面临相同问题的人。

如果您在同一组下有多个应用程序,并且所有应用程序都使用应用程序组(在功能下为ON),则必须从设备中删除所有应用程序,以清除用户默认设置。

由于用户默认设置是共享的,即使设备上有一个应用程序,它也不会被删除,因为该应用程序将使用userdefaults。


4

这是一个bug,你可以通过以下代码删除NSUserDefaults。

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

4
代码应该在设备上运行良好。模拟器可能存在一些错误。 尝试在模拟器中重置内容和设置。

1
重置内容和设置运行良好,目前我没有设备进行检查。谢谢 :) - Reza Shayestehpour

2
在我的情况下,我在以下目录中找到了 *.plist 文件:
[1] /Users/SOME-USERNAME/Library/Developer/CoreSimulator/Devices/SOME-DEVICE-ID/data/Library/Preferences/SP.UserDefaultsTest.plist
问题:在 xCode 6(iOS 8 模拟器)中删除应用程序,但文件仍然保留在磁盘上,就像上面提到的那样。
解决方案:手动从路径 [1] 中删除定位到的文件,NSUserDefault 就会被删除。
因此,不再需要重置模拟器。

2

虽然这仍然是一个 bug,但另一种选择可能是从NSUserDefaults中删除特定的键。大多数情况下,在测试和开发时,我们只关心几个键,而不是NSUserDefaults中的所有内容。如果你只关心几个键,那么我建议使用removeObjectForKey

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
// ADD THIS TO SIMULATE CLEAN/EMPTY DEFAULTS, COMMENT OUT AFTER INITIAL EXECUTION.
// This will cause the TRUE case to be executed.
[userDefaults removeObjectForKey:@"runCount"]

NSLog(@"hello %ld", (long)[userDefaults integerForKey:@"runCount"]);

if ([userDefaults integerForKey:@"runCount"] != 1) {
    //not the 2nd run
    [userDefaults setInteger:1 forKey:@"runCount"];
    NSLog(@"not 2nd run");
} else {
    //second run or more
    NSLog(@"2nd run");
}

[userDefaults synchronize];

添加removeObjectForKey模拟了应用程序的第一次运行,将其注释掉会模拟所有后续的应用程序执行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接