Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 用户默认值有时被错误读取_Ios_Swift_Swift3 - Fatal编程技术网

Ios 用户默认值有时被错误读取

Ios 用户默认值有时被错误读取,ios,swift,swift3,Ios,Swift,Swift3,我一直在开发一个应用程序,在应用程序发布之间存储用户数据(用户名等);我将这些数据存储在UserDefaults中。然而,我最近注意到了一个问题:有时,当我运行应用程序时,我会从UserDefaults.standard.object(forKey:)中获得一些值,但其他时候,当我知道存在某个事实时,我会得到nil 这对我来说毫无意义 我一直在寻找这个问题的答案,但只找到了答案,没有任何帮助 为了测试这一点,我制作了一个空的应用程序,并将以下内容放入viewdide,然后我运行了一次应用程序:

我一直在开发一个应用程序,在应用程序发布之间存储用户数据(用户名等);我将这些数据存储在UserDefaults中。然而,我最近注意到了一个问题:有时,当我运行应用程序时,我会从
UserDefaults.standard.object(forKey:)
中获得一些值,但其他时候,当我知道存在某个事实时,我会得到
nil

这对我来说毫无意义

我一直在寻找这个问题的答案,但只找到了答案,没有任何帮助

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

UserDefaults.standard.setValue("aValue", forKey: "aKey")
上面这一行只是为了确保实际上存储了一个值。然后,我从
视图中删除了上面的一行,然后将其放入
中,并使用选项完成启动:

print(UserDefaults.standard.object(forKey: "aKey") as? String)
然后我运行了20次应用程序。这是我的数据,如果
打印(…)
打印
nil
“aValue”


✓  如果在视图控制器中出现的
viewdide
之后调用AppDelegate中的
didfishlaunchingwithoptions
,则可能发生这种情况

苹果公司推荐的方法是尽快注册所有键/值对(
awakeFromNib
应用程序将完成启动

默认值
“aValue”
在第一次被覆盖之前一直被考虑。 如果重置应用程序的数据,将再次读取默认值

这是最可靠的方法


注:永远不要将
valueForKey:
setValue:forKey:
UserDefaults一起使用
,因为它们是不相关的,您不知道它们发生的顺序,甚至不知道
viewdideappear
是否会发生(毕竟不是每个视图控制器都会出现)

将它们放在同一位置以运行测试。例如,让我们将它们都放在
didfishLaunching
中:

你会发现,这正是你所期望的


编辑好的,多亏了你发布的电影,我们看到了一个复杂问题:你正在设备上测试这个。您通过反复点击Xcode中的Run按钮来进行测试,但没有以一致的方式停止应用程序,这可能会混淆Xcode,使其进行完全替换,或者使其无法在第一时间将默认值写入磁盘。相反,运行,切换到设备并点击Home按钮,现在切换回Xcode并停止。现在再跑一次。我想你会发现你会得到一个更一致的结果。

你能尝试在创建密钥的部分之后添加
UserDefaults.standard.synchronize()
。或者尝试在viewDidLoad中打印它,它可能以前没有加载过。您是否在运行应用程序后删除它?或者你只是想停止它?@Eric,
.setValue…
代码只是在第一次运行时才出现的,只是为了在那里有一个值。所有后续运行只有
.object…
code@J.Koush,我只是停止它,而不是删除。可能是这样吗?对不起,我想可能不清楚我是如何描述我的情况的:
.setValue…
代码只在第一次运行时存在,只是为了在那里有一个值。所有后续运行只有
.object…
代码。我在我的问题中所做的试验是针对那些后来的runsI编辑了我的问题,因为我以前写的方式是误导性的。我很抱歉。现在应该非常清楚,无论如何,您可以防止注册密钥/值对的意外行为。因此,设置用户默认值的正确方法是说
。注册(默认值:)
,而获取用户默认值的正确方法是说
。对象(forKey:)
?不,注册是设置默认值的任务(正如类的名称所暗示的)有
集合(:forKey
写入和
对象/string/integer/bool/etc(forKey:
阅读。请阅读课堂文档。我编辑了我的问题。我以前写的方式有误导性。对不起。我不打算编辑我的答案。如果你照我说的做,一切都会好的。试试。只需输入此代码,不要更改它。只需反复运行应用程序,看看会发生什么。我将你的代码粘贴到
d中idFinishLaunching
,运行了两次,两次都打印了
,设置它
,要么是你弄错了,要么是你在做其他事情(有其他代码或其他事情)。我创建了应用程序,粘贴了代码,运行了它,看到了预期的“没有得到,设置了”。然后我立即一次又一次地运行,看到了每次都是“明白了”。我只运行了4次,直到第四次它才说“明白了”。你的代码是我添加到项目中的唯一内容。
✓ It could happen if 
didFinishLaunchingWithOptions
in AppDelegate is called after
viewDidAppear
in the view controller.

The recommended way (by Apple) is to register all key / value pairs as soon as possible (
awakeFromNib
or
applicationWillFinishLaunching
)

let defaultValues = ["aKey" : "aValue"]
UserDefaults.standard.register(defaults: defaultValues)
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")
}