【发布时间】:2018-09-21 15:49:13
【问题描述】:
这种情况有点过于复杂,无法用语言来描述,所以我创建了一个最小的演示项目供您下载和运行:
https://github.com/mattneub/DefaultsDemo
您将需要 Xcode 10 进行测试。这是项目运行时的样子:
项目代码似乎有很多不必要的混乱,但那是因为我已经包含了我的 real 应用程序(纸牌游戏)中的最少材料来重现我的问题'我看到了。有一副卡片和卡片布局,想法是当用户单击主页按钮时,我们会收到应用程序将退出活动的通知,我们将卡片组和卡片布局保存到 UserDefaults 中。当我们重新启动时,我们会检索牌组和卡牌布局,然后用户就可以继续玩了。
但它不能正常工作,我将解释。而实际上测试看现象很简单:
在模拟器上运行项目。
按三到五次左右随机播放按钮。 (如果你的牌开始用完了,请点击 New Deck 按钮。但在我的测试中,这通常不是必需的。)
点击模拟器上的主页按钮。这使我们保存到 UserDefaults。查看 Xcode 控制台;它告诉您有许多卡片在刚刚保存到 UserDefaults 中的卡片组中。记住那个号码!
-
返回 Xcode,停止项目并再次运行它,从第 1 步重新开始。当我们启动时,您会被告知牌组中有多少张卡片是刚刚从 UserDefaults 中检索到的。
不断重复这四个步骤。发生在我身上的是,大约两三个周期后,第 4 步中的数字与第 3 步中的数字不同。我们没有从 UserDefaults 中返回我们刚才保存到 UserDefaults 中的同一套牌!
此外,关于这个错误的数字,我可以多说几句:它是我们在较早的场合保存到 UserDefaults 中的牌组中的牌张数。就好像 UserDefaults 已经以某种方式悄无声息地损坏并停止接受新版本的套牌。
为了说明,我刚刚清理了模拟器并打开了项目,我将运行它并告诉你我在控制台中看到了什么(用 cmets 解释我做了什么):
81 // launch
65
starting fresh 65
62 // shuffle
59 // shuffle
56 // shuffle
saving 56 // Home button
好的,让我们再次从 Xcode 启动:
retrieving 56 // launch
53 // shuffle
50 // shuffle
47 // shuffle
44 // shuffle
saving 44 // Home button
好的,让我们再次从 Xcode 启动:
retrieving 56 // launch
这就是错误!我们落后了;我们正在从上一个存档中取回套牌,而不是我们刚刚进行的存档中的套牌。 (我实际上可以通过打印牌组来证明这一点;它有一个description 属性就是为了这个目的,我实际上可以看到这是之前保存的牌组。)
所以问题是:为什么?我知道如何解决它;保存到文件而不是 UserDefaults。但我想知道导致这个问题的 UserDefaults 是怎么回事。我怀疑我保存到 UserDefaults 中的一个对象会导致某种静默损坏,但我不明白这是怎么回事,因为它们只是 Data 对象。
(顺便说一句,调用synchronize 不会改变任何事情,并且在任何情况下,它都会根据标题被弃用,尽管尚未正式如此。)
【问题讨论】:
-
可能就是这样。由于
UserDefaults是异步保存的,可能需要等待一两分钟才能重新运行应用程序。我只是看了你的代码。在willResignActiveNotification块中设置deckArchive后尝试调用UserDefaults.standard.synchronize()。也许这可以解决它? -
这里的行为相同。这很可能是一个时间问题(甚至可能是一个错误),它破坏了更新默认数据库的工作流程。使用
synchronize()强制更新并在重新启动应用程序之前等待几秒钟似乎可以解决问题。错误是否也出现在设备上? -
@Pranay 我应该提到调用
synchronize不会改变任何东西,并且它已被弃用(参见标题)。 -
@matt 啊!我很抱歉。我不知道它已被弃用。尽管如此,这似乎是一个非常奇怪的问题。
-
@vadian 是的,在设备上也是如此。
标签: ios nsuserdefaults