Swift - Coredata Migration - 根据旧属性值设置新属性值 [英] Swift - Coredata Migration - Set new attribute value according to old attribute value
问题描述
我当前的核心数据实体之一 - Entity1 - 有一个名为 isSaved
的 Boolean
属性.
One of my current core data entities - Entity1 - has a Boolean
attribute called isSaved
.
在新的核心数据模型中,我计划删除 isSaved
属性并添加一个名为 type
的新 Int
属性.对于所有保存的 Entity1 对象,我想根据旧核心数据模型中 isSaved
的值设置 type
的值.(例如,如果 isSaved 为真,则类型为 1,否则类型为 2).
In the new core data model, I am planning to remove isSaved
attribute and add a new Int
attribute called type
. And for all saved Entity1 objects, I'd like to set the value of type
according to the value of isSaved
in old core data model. (e.g. if isSaved is true, then type is 1, else type is 2).
我读过一些关于轻量级核心数据迁移的文章,但似乎都没有帮助.
I've read some articles about light weight core data migration, but none of them seems helpful.
只是想知道是否有任何方法可以使我计划的迁移工作?
Just wondering if there is any way that can make my planned migration work?
推荐答案
轻量级迁移无法做到这一点.您必须创建一个映射模型和一个 NSEntityMigrationPolicy
的子类.这并不难,但对于大多数 iOS 开发人员来说,这是一个陌生的领域.步骤如下:
Lightweight migration can't do this. You'll have to create a mapping model and a subclass of NSEntityMigrationPolicy
. It's not difficult but it's unfamiliar territory for most iOS developers. The steps run like this:
- 创建映射模型.在 Xcode 中,文件 -->新 -->映射模型.当您单击下一步"时,Xcode 将询问此映射的源(旧)和目标(新)模型文件.
- 模型文件将在可能的情况下推断映射.其他一切都将是空白的.使用您的
type
和其他一些属性,它看起来像下面这样.$source.timestamp
之类的条目表示从迁移之前复制现有值.
- Create the mapping model. In Xcode, File --> New --> Mapping Model. When you click "Next", Xcode will ask for the source (old) and destination (new) model files for this mapping.
- The model file will infer mappings where possible. Everything else will be blank. With your
type
and some other properties, it'll look something like the following. Entries like$source.timestamp
mean to copy the existing value from before the migration.
创建一个
NSEntityMigrationPolicy
的新子类.为子类指定一个明显的名称,例如ModelMigration1to2
.这个类将告诉 Core Data 如何将旧的布尔值映射到新的整数值.
Create a new subclass of
NSEntityMigrationPolicy
. Give the subclass an obvious name likeModelMigration1to2
. This class will tell Core Data how to map the old boolean value to the new integer value.
给子类添加一个方法来转换值.类似于以下内容.方法名称无关紧要,但如果您选择一些描述性的东西,那就很好了.你需要在这里使用 ObjC 类型——例如NSNumber
而不是 Int
和 Bool
.
Add a method to the subclass to convert the value. Something like the following. The method name doesn't matter but it's good if you choose something descriptive. You need to use ObjC types here-- e.g. NSNumber
instead of Int
and Bool
.
@objc func typeFor(isSaved:NSNumber) -> NSNumber {
if isSaved.boolValue {
return NSNumber(integerLiteral: 1)
} else {
return NSNumber(integerLiteral: 2)
}
}
返回映射模型并告诉它使用您的子类作为其自定义映射策略.那是在自定义策略"下右侧的检查器中.请务必包含模块名称和类名称.
Go back to the mapping model and tell it to use your subclass as its custom mapping policy. That's in the inspector on the right under "custom policy". Be sure to include the module name and class name.
- 告诉映射模型使用您之前创建的函数从旧的
isSaved
属性中获取type
属性的值.下面说用一个参数调用名为typeForIsSaved:
(:
很重要)的自定义策略类上的函数,并且该参数应该是isSaved
$source
上的值(旧的托管对象).
- Tell the mapping model to use that function you created earlier to get values for the
type
property from the oldisSaved
property. The following says to call a function on the custom policy class namedtypeForIsSaved:
(the:
is important) with one argument, and that the argument should be theisSaved
value on$source
(the old managed object).
迁移应该现在有效.您不必告诉 Core Data 使用映射模型——它会确定需要迁移并寻找与新旧模型版本匹配的模型.
Migration should now work. You don't have to tell Core Data to use the mapping model-- it'll figure out that migration is needed and look for a model that matches the old and new model versions.
一些注意事项:
- 如果您因类似于
Couldn't create mapping policy for class named...
之类的错误而崩溃,那么您在第 5 步中忘记了上面的模块名称(或弄错了).莉> - 如果您因
unrecognized selector
错误而崩溃,则第 4 步中的方法签名与您在第 6 步中输入的不匹配.如果您忘记包含,也会发生这种情况@objc
在函数声明中.
- If you crash with an error that's something like
Couldn't create mapping policy for class named...
then you forgot the module name above in step 5 (or got it wrong). - If you get a crash with an
unrecognized selector
error then the method signature in step 4 doesn't match what you entered in step 6. This can also happen if you forget to include@objc
in the function declaration.
这篇关于Swift - Coredata Migration - 根据旧属性值设置新属性值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!