我一直在开发一个应用程序,可以在应用程序启动之间存储用户数据(用户名等);我将此数据存储在 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"
,这是我的数据:
✓ 𐄂 𐄂 𐄂 ✓ 𐄂 ✓ ✓ ✓ ✓ ✓ ✓ 𐄂 ✓ ✓ ✓ 𐄂 ✓ ✓ 𐄂
它打印 nil
的概率为 35%,在我看来它也相当随机。
我有两个问题:
为什么会发生这种情况,我该如何解决/预防这种情况?
最佳答案
把 set
放在 viewDidAppear
而 get
放在 didFinishLaunching
是很疯狂的,因为它们是不相关的并且您对它们发生的顺序一无所知,甚至不知道 viewDidAppear
是否会曾经发生(毕竟不是每个 View Controller 都会出现)。
将它们放在同一个地方以运行测试。例如,让我们将它们都放在 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 并停止。现在再次运行。我想您会发现您会得到更一致的结果。
关于ios - UserDefaults 有时被错误读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40823066/