使用Core Data + iCloud同步时,在应用程序和Today小部件之间共享数据的正确方法

3
我有一个带有今天小部件扩展的应用程序。我需要应用程序、小部件和其他设备上的应用程序和小部件共享数据,因此我正在使用iCloud Core Data集成。起初,我让应用程序和小部件(在单个设备内)共享相同的Core Data存储库(sqlite)在一个共享容器目录中。现在我已启用了iCloud同步,在设备之间工作,但现在我在同一设备上的应用程序和小部件之间显示不一致的数据(?!)。问题可能出在我的小部件GUI更新周期或通知中心订阅上,我仍在排除故障,但同时我想问一下:

当您使用Core Data + iCloud时,在同一设备上的应用程序和小部件之间共享Core Data数据的“正确”解决方案是什么?它们应该共享单个物理存储,还是各自拥有自己的存储?如果这两种方法都有效,则是否存在陷阱?


苹果公司的Lister演示应用提供了一个工作示例。 - Tom Harrington
1个回答

3
你应该首先考虑的问题是是否真正需要与扩展共享整个Core Data存储。如果可能只需通过plist共享一些数据,将使事情变得简单得多。
假设这不是一个选项,你确实需要整个存储库,那么你有两个选择:
1.在共享容器中共享单个存储
2.采用Core Data同步解决方案,并为主应用程序和扩展使用单独的存储。
可以在两个独立的进程之间共享单个存储,但有一些要注意的地方。如果一个进程保存,第二个进程中的任何NSManagedObjectContext都不会注册更改,这意味着数据不会在UI中更新,并且还可能导致稍后保存失败。
为了避免这种情况,您需要找到一种方法来传递已更改对象的对象ID,以便接收进程可以刷新对象并重新获取最新数据。
第二个选项涉及两个单独的存储库和传输更改的方法。如果你选择iCloud + Core Data,则iCloud是传输机制,这有点过度kill,因为你的进程都在同一设备上。
我相信苹果甚至警告iOS不要使用这个解决方案,因为如果一个iOS应用程序进入后台,当文件协调器锁定一个文件时,它可能会被停止,这可能会导致其他进程中的死锁。
iCloud + Core Data并不是唯一的同步解决方案。在这种情况下更好的解决方案可能是Ensembles框架,我开发了这个框架。我之所以这样说是因为它提供了通过本地文件进行同步的选项,而不需要云服务。您可以为扩展和主应用程序设置单独的存储,并让Ensembles使用共享容器来传输更改集。没有云参与,也没有文件协调问题。

谢谢@Drew,我听说过Ensembles,并且实际上已经阅读了你在objc.io上的数据同步文章。两个澄清:1.是的,我认为我需要将足够大的模型块提供给小部件,并且小部件需要编写数据,因此我不认为第二个持久化层是一个好主意。2.我确实有跨设备同步的要求,除了在设备上同步之外-因此使用云或P2P同步并不会增加额外开销,必须进行投资。我一直在针对Core Data + iCloud,因为它似乎是KISS解决方案,但我会重新审视Ensembles。 - S'pht'Kr
我开始寻找基于文件协调锁定的苹果推荐,用于两个进程之间的通信。我认为这就是你想要的,但它似乎建议不要使用.plist文件或其他平面文件进行协调,实际上它说:“相反,使用CFPreferences、原子安全保存操作的平面文件、SQLite或Core Data。”这很有道理,我想(希望?)Core Data使用某种原子文件操作,不能被应用程序挂起轻易中断。 - S'pht'Kr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接