NSUserDefaults 线程在 IOS 上的扩展之间共享数据是不是安全?
Posted
技术标签:
【中文标题】NSUserDefaults 线程在 IOS 上的扩展之间共享数据是不是安全?【英文标题】:Is NSUserDefaults thread safe for sharing data between extensions on IOS?NSUserDefaults 线程在 IOS 上的扩展之间共享数据是否安全? 【发布时间】:2014-10-12 08:59:49 【问题描述】:“与包含的应用程序共享数据”下的应用程序扩展文档使用 NSUserDefaults 来执行此操作,并进一步写了一点
“为避免数据损坏,您必须同步数据访问。使用 Core Data、SQLite 或 >Posix 锁来帮助协调共享容器中的数据访问。”
但是当我查看 NSUserDefaults 的文档时说
“NSUserDefaults 类是线程安全的。”
那么在我的扩展程序和容器应用程序之间使用 NSUserDefaults 时是否需要使用某种锁?
【问题讨论】:
【参考方案1】:线程安全是指从一个线程更改内存中数据结构的能力,而不会损害其他线程也查看或更改这些结构的能力。当您使用NSUserDefaults
在应用扩展及其包含的应用之间共享数据时,您不是在多个线程之间共享内存中的数据,而是在多个之间共享磁盘上数据>进程,因此线程安全的讨论不适用。
NSUserDefaults
synchronize
的文档并没有肯定地说,但几乎可以肯定的是,它使用原子文件写入——也就是说,一个进程读取由另一个过程。如果您担心应用写入默认值和扩展读取它们之间的竞争条件或其他时间问题(反之亦然),请务必在重要写入之后和重要读取之前立即发送synchronize
。
关于数据损坏的评论适用于普通文件读/写操作 - 在两个进程中天真地读取或写入文件可能会导致数据损坏,因为一个进程可能会读取部分写入的文件或部分覆盖文件内容。如果您直接进行自己的文件 I/O,则需要某种协调机制(例如 NSFileCoordinator
,但请注意,只有在 ios 应用程序/扩展程序之间才能正常工作 in iOS 8.2 and newer)。或者,您可以使用自行协调的更高级别的实用程序,例如 CFPreferences
/NSUserDefaults
、SQLite、Core Data 或 Posix 文件锁。
TLDR:是的,您可以安全地使用NSUserDefaults
在扩展程序及其包含的应用程序之间共享。只需遵循in Apple's app extensions guide 的建议即可。
【讨论】:
【参考方案2】:文档并不太清楚,因为它使用NSUserDefaults
作为共享数据的一种方式的主要示例,但也涵盖了其他选项而没有太多停顿。您应该足够安全地使用NSUserDefaults
而无需先尝试获得锁,我一直在使用它构建一个 Today 扩展,并且我没有遇到数据损坏的问题。我在每次写入后都会调用synchronize
,只是为了确保立即存储数据。
【讨论】:
以上是关于NSUserDefaults 线程在 IOS 上的扩展之间共享数据是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章
iOS 8,9 上的 NSUserDefaults 有多安全?
从 iOS 上的 React Native 应用程序访问 NSUserDefaults