4

“与包含的应用程序共享数据”下的应用程序扩展文档使用 NSUserDefaults 来执行此操作,并进一步写下

“为避免数据损坏,您必须同步数据访问。使用 Core Data、SQLite 或 >Posix 锁来帮助协调共享容器中的数据访问。”

但是当我查看 NSUserDefaults 的文档时说

“NSUserDefaults 类是线程安全的。”

那么在我的扩展程序和容器应用程序之间使用 NSUserDefaults 时是否需要使用某种锁?

4

2 回答 2

4

线程安全是指在不损害其他线程也查看或更改这些结构的能力的情况下,从一个线程更改内存中数据结构的能力。当您用于NSUserDefaults在应用程序扩展及其包含的应用程序之间共享数据时,您不是在多个线程之间共享内存中的数据,而是在多个进程之间共享磁盘上的数据,因此线程安全的讨论不适用。

的文档NSUserDefaults synchronize并没有肯定地说,但几乎可以肯定地假设它使用原子文件写入——也就是说,一个进程读取一个由另一个进程部分写入的文件是没有危险的。如果您担心应用程序写入默认值和扩展读取它们之间的竞争条件或其他时间问题(反之亦然),请确保synchronize在重要写入之后和重要读取之前立即执行。

关于数据损坏的评论适用于普通文件读/写操作——天真地在两个进程中读取或写入文件可能会导致数据损坏,因为一个进程可能会读取部分写入的文件或部分覆盖文件内容。如果您直接进行自己的文件 I/O,则需要某种协调机制(例如NSFileCoordinator,但请注意,只有在 iOS 8.2 和更新版本的iOS 应用程序/扩展之间才能正常工作)。或者您可以使用更高级别的实用程序来进行自己的协调,例如CFPreferences/ NSUserDefaults、SQLite、Core Data 或 Posix 文件锁。

TLDR:是的,您可以安全地用于NSUserDefaults在扩展程序及其包含的应用程序之间共享。只需遵循Apple 应用扩展指南中的建议即可。

于 2016-01-07T20:43:24.933 回答
1

文档并不太清楚,因为它使用 的NSUserDefaults作为共享数据的一种方式的主要示例,但也涵盖了其他选项而没有太多停顿。您应该可以安全地使用NSUserDefaults而无需先尝试获得锁定,我一直在使用它构建 Today 扩展,并且我没有遇到数据损坏的问题。不过,我synchronize在每次写入后都会调用,只是为了确保立即存储数据。

于 2014-10-12T10:05:34.627 回答