注意:我在Stack Overflow上看到很多关于NSUserDefaults
在Swift中重命名为UserDefaults
的帖子,或者在重启之前没有在模拟器上工作。无论如何,这不是重复。 SO标记的许多问题来自4年前。我的问题是今年特定于iOS 10,因为它一直适用于旧版本。我已经在我的问题中提到我的问题不是那些问题的重复,因为那些是swift中的模拟器错误,我的问题是设备目标C bug。 请在标记为重复之前阅读问题
我的问题不同,因为我能够在目标C和物理设备上重现这一点。
我从头开始为这个测试创建了一个全新的项目。我将此代码放在视图控制器的viewDidLoad
中:
if (![[NSUserDefaults standardUserDefaults] valueForKey:@"checkIfInitialized"]){
NSLog(@"setting checkIfInitialized as not exist");
[[NSUserDefaults standardUserDefaults] setValue:@"test" forKey:@"checkIfInitialized"];
[[NSUserDefaults standardUserDefaults] synchronize];
self.view.backgroundColor=[UIColor redColor];
self.mylabel.text=@"NSUserDefaults was NOT there, try running again";
} else {
NSLog(@"checkIfInitialized exists already");
self.view.backgroundColor=[UIColor blueColor];
self.mylabel.text=@"NSUserDefaults was already there this time, try running again";
}
现在,如果我运行应用程序大约10次,几次就会找到checkIfInitialized
,有时则不会。没有确切的数字,它失败了多少次因为它可能会工作3次然后失败2次然后工作4次而失败一次等等。
现在我注意到了(虽然不是100%肯定),但是当我通过Xcode测试连接时,问题似乎才会发生。如果我通过点击没有Xcode的设备上的应用程序图标启动应用程序来运行,那么它似乎工作正常,但我无法100%确定。
我注意到有时会发生这种错误:
[User Defaults] Failed to write value for key checkIfInitialized in CFPrefsPlistSource<0x1700f7200> (Domain: com.xxxx.appname, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null)): Path not accessible, switching to read-only
如果你想测试一下,我在Dropbox上有这个非常简单的项目。 我建议测试大约10-15次来重现这个问题。
https://www.dropbox.com/s/j7vbgl6e15s57ix/nsuserdefaultbug.zip?dl=0
这在iOS 9上完全正常,所以肯定与iOS 10有关。
修改 错误记录:28287988
来自苹果DTS团队的回复:
首先,您应首先确定standardUserDefaults还是 valueForKey失败。我的猜测是“standardUserDefaults” 返回NULL,如果是这样的话,那就是你 一般应该防范。值得注意的是,standardUserDefaults 如果首选项文件在中加密,则返回NULL 应用程序当前正在运行的环境(例如,首选项 设置为“NSFileProtectionComplete”并且应用程序正在运行 背景)。这不应该是标准前景的问题 应用程序,但无论如何都要注意这一点。
Xcode很可能实际上是在这里引发问题。 Xcode以一种非常复杂的方式使应用程序启动环境复杂化 与标准应用程序发布完全不同。我猜这是 基本上由Xcode的时间触发引发预期 应用程序启动期间的情况,但如果您想要更正式的测试 尝试在applicationDidFinishLaunching中设置一个断点 一击到它就继续调试器。我的猜测是 只是添加它会破坏时间足以阻止问题 发生。有点。从iOS 9的意义上说它只是iOS 10 从不打印该日志消息,但那是因为日志消息是 在iOS 10中添加。代码本身与iOS 9.3相似 怀疑完全相同的行为(至少在理论上)是可能的 iOS 9。
答案 0 :(得分:9)
是的,这绝对是一个可以重现的错误。
错误发生在设备和模拟器上。它是间歇性的:保存将工作六次然后失败。与你不同,我没有得到&#34;未能写出密钥&#34;消息。
直接在没有Xcode的设备上操作时也会出现错误。这实际上就是我发现它的方式。
你应该report a bug to Apple,特别是因为你有一个可以重现它的短程序。我也会这样做。
一个关键区别:在我的情况下,失败是写默认值。先前写入的值仍保留在NSUserDefaults中。有时一个键成功写入而另一个键未更改。
答案 1 :(得分:0)
来自我自己的支持请求的同样非常智能的DTS响应。基本上,使用Xcode进行杀戮比在设备上自然发生的任何事情都更具杀气力(即使是双Home-click-and-upwipe方法),并且由于Xcode暂停时所有内容都突然崩溃,因此NSUserDefaults的懒惰写入可能会失败,或只完成一半。
事实上,在没有涉及Xcode的情况下对应用程序进行纯粹的设备上测试表明,当应用程序终止时,所有内容都会正确写入NSUserDefaults。
我已经关闭了自己的错误报告。