iOS UserDefaults落后于保存的内容

时间:2018-09-21 15:49:13

标签: ios nsuserdefaults

这种情况太过复杂,无法用简单的语言来描述,因此我创建了一个最小的演示项目供您下载和运行:

https://github.com/mattneub/DefaultsDemo

您将需要Xcode 10进行测试。这是项目运行时的样子:

enter image description here

该项目代码似乎有很多不必要的混战,但这是因为我包含了我的 real 应用程序(纸牌游戏)中的最小内容以重现我的问题。我在看有一个纸牌和一个纸牌布局,其想法是当用户单击“主页”按钮时,我们会收到一条通知,通知该应用程序将退出活动状态,并将纸牌和纸牌布局保存到UserDefaults中。重新启动时,我们会检索套牌和纸牌布局,并且用户可以继续玩游戏。

但是,正如我将要解释的那样,它无法正常工作。实际上,测试来查看现象很简单:

  1. 在模拟器上运行项目。

  2. 按“随机播放”按钮三到五次左右。 (如果您开始用完所有卡片,请点击“ New Deck”按钮。但是在我的测试中,通常没有必要。)

  3. 在模拟器上单击“主页”按钮。这导致我们保存到UserDefaults中。查看Xcode控制台;它表明您有许多卡刚刚保存到UserDefaults中。记住那个数字!

  4. 返回Xcode,停止项目并再次运行它,从步骤1开始。在启动时,系统会告诉您刚从UserDefaults中检索到的卡中有多少张卡。

    < / li>

继续重复这四个步骤。我发生的事情是,在大约两个或三个周期之后,步骤4中的数字与步骤3中的数字有所不同。我们没有从UserDefaults找回刚才存储在UserDefaults中的同一卡座!

此外,对于这个错误的数字,我可以说更多:它是我们早些时候保存到UserDefaults 中的卡组中的卡数。好像UserDefaults已经以某种方式无声地损坏了并且已经停止接受平台的新版本一样。

为说明起见,我刚刚清理了模拟器并打开了项目,然后将其运行并告诉您我在控制台中看到的内容(带有注释以解释我的所作所为):

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中的一个对象引起了某种程度的无声破坏,但是我不知道怎么回事,因为它们只是数据对象。

(顺便说一句,调用synchronize并不会改变任何东西,尽管在形式上尚未正式使用,但无论如何它都根据标头被弃用。)

1 个答案:

答案 0 :(得分:0)

我将建议整个项目是一个红鲱鱼,问题在于您的测试过程

我认为 UserDefaults保存缓慢:对UserDefaults进行更改仅花费很长时间才能“接受”,甚至在出现以下所有信号后 已经发生(synchronize已返回,didChange通知已到达,依此类推)。

因此,我敢打赌,您只是在按下“主页”按钮和再次运行应用程序之间没有足够的时间。要看到可能是这样,请进行以下更改:不要直接从第3步转到第4步,而是插上第3a步,即缓慢地计数到10。现在,该错误不会显现出来。

(也可以说在willResignActiveNotification时保存是错误的。保存的时间就是相关数据发生变化的时间!因此,在测试示例中,我们应该在每次改组结束时保存-交易操作-不在用户点击“主页”按钮时显示。)