Swift – Coredata迁移 – 根据旧的属性值设置新的属性值
我当前的核心数据实体之一 – Entity1 – 具有一个名为isSaved
的Boolean
属性。
在新的核心数据模型中,我计划删除isSaved
属性并添加一个名为type
的新的Int
属性。 对于所有保存的Entity1对象,我想根据旧核心数据模型中的isSaved
值设置type
的值。 (例如,如果isSaved为true,则type为1,否则type为2)。
我已经阅读了一些关于轻量级核心数据迁移的文章,但没有一篇似乎有帮助。
只是想知道是否有什么方法可以使我计划的迁移工作?
轻量级迁移不能做到这一点。 你将不得不创build一个映射模型和NSEntityMigrationPolicy
的子类。 这并不困难,但对于大多数iOS开发人员来说这是陌生的领域。 步骤如下所示:
- 创build映射模型。 在Xcode中,文件 – >新build – >映射模型。 当你点击“下一步”时,Xcode会询问这个映射的源(旧)和目标(新)模型文件。
- 模型文件将尽可能地推断映射。 其他一切都将是空白的。 随着你的
type
和其他一些属性,它会看起来像下面这样。 像$source.timestamp
这样的条目意味着复制迁移之前的现有值。
-
创build一个
NSEntityMigrationPolicy
的新子类。 给这个子类一个明显的名字,比如ModelMigration1to2
。 这个类将告诉核心数据如何将旧的布尔值映射到新的整数值。 -
向子类添加一个方法来转换值。 像下面这样。 方法名称并不重要,但如果select描述性的内容,则很好。 你需要在这里使用ObjCtypes – 例如
NSNumber
而不是Int
和Bool
。func typeFor(isSaved:NSNumber) -> NSNumber { if isSaved.boolValue { return NSNumber(integerLiteral: 1) } else { return NSNumber(integerLiteral: 2) } }
-
回到映射模型,并告诉它使用你的子类作为它的自定义映射策略。 这是在“自定义策略”右侧的检查员。 确保包含模块名称和类名称。
- 通知映射模型使用您之前创build的函数从旧的
isSaved
属性获取type
属性的值。 下面说调用一个名为typeForIsSaved:
的自定义策略类上的一个函数typeForIsSaved:
:
是重要的)有一个参数,并且参数应该是$source
(旧的被pipe理对象)上的isSaved
值。
现在移民工作。 您不必告诉核心数据使用映射模型 – 它会发现需要迁移,并寻找一个匹配旧的和新的模型版本的模型。
几个注意事项:
- 如果你崩溃的错误是类似的
Couldn't create mapping policy for class named...
那么你忘了上面的模块名称在步骤5(或错误的)。 - 如果遇到
unrecognized selector
错误,则步骤4中的方法签名与您在步骤6中input的内容不匹配。
使用Xcode 9.1 Beta与Swift 4,我发现迁移的作品,但你必须小心如何指定变换方法的名称,也似乎你需要将你的函数标记为@objc。
例如,我的价值expression:
FUNCTION($entityPolicy, "changeDataForData:" , $source.name)
我的转换策略方法名称:
class StudentTransformationPolicy: NSEntityMigrationPolicy { @objc func changeData(forData: Data) -> String { return String(data: forData, encoding: .utf8)! } }
在模型更改之后启动我的应用程序之前,我需要进行大量的试验才能触发。 如果所有这些都不起作用,那么为您的策略实施“createDestinationInstances”可能会更容易,但是我们将在另一天离开这个…