UserDefaults有时被错误地读取

时间:2016-11-26 20:56:46

标签: ios swift swift3

我一直在开发一个应用程序,用于在启动应用程序之间存储用户数据(用户名等);我将这些数据存储在UserDefaults中。但是,我最近发现了一个问题:有时候,当我运行应用程序时,我会从UserDefaults.standard.object(forKey:)获得一些价值,但有时候当我知道有一个事实时我会得到nil那里的东西。

这对我没有意义。

我在SO上搜索了这个问题的答案,但只找到了this,但没有帮助。

为了测试这个,我制作了一个空的应用程序并将以下内容放在viewDidAppear中,然后我运行了一次应用程序:

UserDefaults.standard.setValue("aValue", forKey: "aKey")

以上一行只是为了确保实际存储了一个值。然后,我从viewDidAppear删除了上述行,然后将其放在didFinishLaunchingWithOptions

print(UserDefaults.standard.object(forKey: "aKey") as? String)

然后我运行了20次应用程序。以下是print(...)打印nil"aValue"

的数据
✓    ✓  ✓ ✓ ✓ ✓ ✓ ✓  ✓ ✓ ✓  ✓ ✓ 

它在35%的时间内打印nil,在我看来也相当随意。

我有两个问题:

为什么会发生这种情况,我该如何解决/阻止它?

2 个答案:

答案 0 :(得分:1)

如果在视图控制器中didFinishLaunchingWithOptions之后调用AppDelegate中的viewDidAppear,则可能会发生这种情况。

建议的方法(由Apple)尽快注册所有键/值对(awakeFromNibapplicationWillFinishLaunching

let defaultValues = ["aKey" : "aValue"]
UserDefaults.standard.register(defaults: defaultValues)

默认值"aValue"将被考虑,直到第一次被覆盖。 如果您重置应用程序的数据,则会再次读取默认值。

这是最可靠的方式。

PS:切勿将valueForKey:setValue:forKey:UserDefaults

一起使用

答案 1 :(得分:1)

set放在viewDidAppearget放在didFinishLaunching中是很疯狂的,因为它们是无关的,你对订单一无所知它们将在何时发生,甚至viewDidAppear永远发生(毕竟不是每个视图控制器都会出现)。

将它们放在同一个地方进行测试。例如,我们将它们都放在didFinishLaunching

let val = UserDefaults.standard.object(forKey: "aKey") as? String
if val != nil {
    print("got it")
} else {
    print("didn't get it, setting it")
    UserDefaults.standard.set("aValue", forKey: "aKey")
}

您会发现这样可以正常运作。

编辑好的,感谢你发布的电影,我们发现有一个复杂的问题:你在设备上测试了这个。您正在通过反复按Xcode中的“运行”按钮进行测试,而不会以一致的方式停止应用程序,这可能会使Xcode混淆,以便它完全替换,或者在第一次执行时永远不会有机会将默认值写入磁盘地点。相反,运行,切换到设备并点击主页按钮,现在切换回Xcode和停止。现在再跑一次。我想你会发现你会得到更一致的结果。