何时以及为什么要使用NSUserDefaults的synchronize()方法?

时间:2016-11-25 15:20:02

标签: ios performance nsuserdefaults

所以我看了一下NSUserDefaults的synchronize()方法的苹果文档。见下文参考:

https://developer.apple.com/reference/foundation/userdefaults/1414005-synchronize

该页面目前显示为:

  

因为此方法是定期自动调用的,所以只有在您不能等待自动同步时(例如,如果您的应用程序即将退出)或者您希望将用户默认值更新为打开时,才使用此方法即使您没有进行任何更改,也可以使用磁盘。

然而,我仍然不明白这个方法什么时候应该被调用?例如,每次用户更改应用程序的设置时是否应该调用它?或者我应该相信后台api会处理它?并且在内存中的设置更改后立即离开视图会导致更改丢失吗?

此外,如果调用synchronize()失败,导致用户设置无法正确更改?

此外,调用此方法的成本(性能,内存或其他)是多少?我知道它涉及从磁盘读取和写入磁盘,但这确实在手机上花费了很多精力吗?

4 个答案:

答案 0 :(得分:29)

似乎有很多关于用户默认值的混淆。这样想吧。它与您在整个应用中提供全球字典的方式基本相同。如果您向全局字典添加/编辑/删除键/值,则该更改会立即显示在代码中的任何位置。由于这个字典在内存中,如果你的应用程序没有持久存储到文件中,那么所有字典都会丢失。 NSUserDefaults每隔一段时间就会自动将字典保存到文件中。

synchronize方法的唯一原因是您的应用可以告诉NSUserDefaults保留字典"现在"而不是等待最终会发生的自动保存。

您需要这样做的唯一原因是因为您的应用可能会在下次自动保存之前被终止(或崩溃)。

在我自己的应用中,我调用synchronize的唯一地方是applicationDidEnterBackground委托方法。这是为了确保在应用程序在后台终止时保留最新的未保存更改。

我认为很多混乱来自于在开发过程中调试应用程序。在开发期间,您通过"停止"杀死应用程序并不罕见。调试器中的按钮。很多时候,这种情况发生在最近的NSUserDefaults更改持续存在之前。因此,每当我想确保保留最新更新时,我就会在调试器中杀死应用程序之前按下Home按钮将习惯放在后台。

鉴于上述摘要,让我们回顾一下您的问题:

  每当用户更改应用程序的设置时,是否应该调用它?

没有。如上所述,任何更改都会立即自动提供。

  

或者我应该相信后台api会处理它?<​​/ p>

是的,相信自动持久性,但在您的应用进入后台时调用synchronize除外。

  

在内存设置更改后立即离开视图会导致更改丢失吗?

这没有效果。在NSUserDefaults中添加/编辑/删除键/值后,即会进行更改。

  

此外,如果调用synchronize()失败,导致用户设置无法正确更改?

唯一可以丢失更改的是,如果您的应用在最新更改被保留之前被终止。当您的应用进入后台时调用synchronize解决了大部分问题。唯一剩下的可能问题是你的应用程序崩溃了。任何尚未保留的未保存更改都将丢失。修复您的应用,使其不会崩溃。

  

此外,调用此方法的成本(性能,内存或其他)是多少?我知道它涉及从磁盘读取和写入磁盘,但这确实在手机上花费了很多精力吗?

自动持久性在后台完成,它只是将字典写入plist文件。除非您不遵循建议,否则速度非常快。如果您误用NSUserDefaults来存储大量数据,则速度会慢一些。

答案 1 :(得分:5)

Apple的documentation for synchronize()已更新,现在为:

  

等待默认数据库的任何挂起的异步更新并返回; 此方法是不必要的,不应使用

答案 2 :(得分:3)

<强>更新

正如预期的那样,Apple Doc

中提到的已弃用
  

<强>同步()

     

等待默认数据库的任何挂起的异步更新并返回;这种方法是不必要的,不应该使用。

原始答案

FOREIGN KEY (regionId) REFERENCES region (id) ON DELETE CASCADE ON UPDATE CASCADE 将按照here

提及弃用
  

- 同步已弃用,并将在以后的版本中使用NS_DEPRECATED宏进行标记。

     

-synchronize阻塞调用线程,直到所有正在进行的集合操作完成。这不再是必要的。先前使用-synchronize的替换取决于调用synchronize的意图。如果你同步了......

     

- ...在阅读之前为了获取更新的值:删除同步调用

     

- ...写完后为了通知另一个程序读取:其他程序可以使用KVO来观察默认值而无需通知     - ...退出非app(命令行工具,代理或守护程序)进程之前:调用CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication)

     

- ...出于任何其他原因:删除同步调用

答案 3 :(得分:0)

据我所知,synchronize用于立即同步数据,但iOS可以智能方式处理。所以你不需要每次都打电话。如果你每次都打电话,那么它将转向性能问题。

查看Apple文档: Official Link