我有一个应用程序使用 Core Data
来管理我们称之为 lists
的 Entities
。每个列表都有一个 offlineData
属性,类型为 Binary Data
。 Allows External Storage
选项对此适用。
此实体使用以下方法保存一组自定义对象:
NSArray *customObjects;// My custom objects that have been added
self.list.offlineData = [NSKeyedArchiver archivedDataWithRootObject:customObjects];
这会将对象保存到 Core Data
blob,因为所有对象都在使用 initWithEncoder:
和 encodeWithCoder:
。
当用户想要查看列表时,我们执行相反的操作:
NSArray *items = [NSKeyedUnarchiver unarchiveObjectWithData:self.list.offlineData];
问题
起初这似乎是一个很好的解决方案(现在显然很愚蠢),因为我们可以轻松地向对象添加额外的属性等。但是我们没有预料到用户会添加数千个对象。这导致:
- 尝试存档或创建包含数千个对象的数组时出现内存问题和崩溃
- 解档对象时的内存问题
- 根据设备速度,取消存档可能需要很长时间,让用户坐等
- 限制用户可以添加到列表中的对象数量。
- 搜索对象时出现速度问题,因为我无法执行提取请求。
解决方案?
我想到的解决方案是将所有自定义对象迁移到 Core Data
实体。这将是 list entity
和 object entity
之间的To Many
关系。
这似乎可以解决上述问题,但我不是 100% 确定。
有没有人对此有建议,这是否是“迁移”的最佳方式?
最佳答案
按照您的描述迁移到新实体应该可以很好地解决您的问题。在您的新数据模型版本中,您将创建新的列表项实体,删除现有的列表属性,并创建您描述的对多关系。
尽管如此,您不能依赖自动迁移来完成此类操作——您需要自定义流程。我在 a different answer 中描述了这个过程大部分适用于您。您必须创建映射模型和 NSEntityMigrationPolicy
的自定义子类。它并不复杂,但对大多数 iOS 开发人员来说并不熟悉。
与其他答案不同,您需要在 NSEntityMigrationPolicy
子类中实现 createDestinationInstances(forSource:, in:, manager:)
方法。对于您的实体实例,这是您将创建一堆列表项对象的地方。取消存档现有数据 blob 并创建新实例。
请记住,这意味着您必须取消归档所有 现有列表 blob。迁移您描述的场景可能需要一段时间。但是您只需为每个用户执行一次。确保在屏幕上显示一些有用的信息,以便人们知道发生了什么,并确保使用足够大的列表来测试迁移。
Apple 的 docs on custom migrations也可能会派上用场。
关于ios - 将二进制数据对象迁移到核心数据实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41863113/