我当前的核心数据实体之一 - Entity1 - 具有名为Boolean
的{{1}}属性。
在新的核心数据模型中,我计划删除isSaved
属性并添加名为isSaved
的新Int
属性。对于所有保存的Entity1对象,我想根据旧核心数据模型中type
的值设置type
的值。 (例如,如果isSaved为true,则type为1,else type为2)。
我已经阅读了一些关于轻量级核心数据迁移的文章,但它们似乎都没有用。
只是想知道是否有任何方法可以使我计划的迁移工作?
答案 0 :(得分:31)
轻量级迁移无法做到这一点。您必须创建映射模型和NSEntityMigrationPolicy
的子类。对于大多数iOS开发人员而言,这并不困难,但这是一个陌生的领域。步骤如下:
type
和其他一些属性,它看起来如下所示。 $source.timestamp
之类的条目意味着在迁移之前复制现有值。创建NSEntityMigrationPolicy
的新子类。给子类一个明显的名称,如ModelMigration1to2
。该类将告诉Core Data如何将旧布尔值映射到新的整数值。
向子类添加方法以转换值。像下面这样的东西。方法名称并不重要,但如果您选择描述性的内容则很好。你需要在这里使用ObjC类型 - 例如NSNumber
代替Int
和Bool
。
func typeFor(isSaved:NSNumber) -> NSNumber {
if isSaved.boolValue {
return NSNumber(integerLiteral: 1)
} else {
return NSNumber(integerLiteral: 2)
}
}
返回映射模型并告诉它使用您的子类作为其自定义映射策略。那是在“自定义政策”下右侧的检查员。请务必包含模块名称和类名。
type
属性获取isSaved
属性的值。以下说使用一个参数调用名为typeForIsSaved:
的自定义策略类(:
很重要)上的函数,并且该参数应该是isSaved
上的$source
值(旧的托管对象)。迁移现在应该。您不必告诉Core Data使用映射模型 - 它会发现需要迁移并寻找与新旧模型版本匹配的模型。
几点说明:
Couldn't create mapping policy for class named...
的错误,那么您在步骤5中忘记了上面的模块名称(或者说错了)。unrecognized selector
错误而崩溃,则步骤4中的方法签名与您在步骤6中输入的方法签名不匹配。答案 1 :(得分:6)
使用Xcode 9.1 Beta和Swift 4,我发现迁移工作正常,但你必须要小心如何指定转换方法名称,似乎你需要将你的函数标记为@objc。
例如,我的价值表达:
FUNCTION($entityPolicy, "changeDataForData:" , $source.name)
我的转化政策方法名称:
class StudentTransformationPolicy: NSEntityMigrationPolicy {
@objc func changeData(forData: Data) -> String {
return String(data: forData, encoding: .utf8)!
}
}
绝对棘手并且在模型更改后启动我的应用程序时触发它之前需要进行大量实验。它可能更容易实现" createDestinationInstances"对于你的政策,如果所有这些都不起作用,但我们会将其留下另一天......