自定义迁移期间没有核心数据实体子类

时间:2017-02-07 21:04:28

标签: core-data migration

我有一个核心数据库。我正在执行自定义迁移。我有一个NSEntityMigrationPolicy的子类。我的政策的迁移方法buildValueFromSectionFieldManagedObject:由映射规则调用:FUNCTION($entityPolicy, "buildValueFromSectionFieldManagedObject:" , $source)

这部分实际上正在运作。

但是,buildValueFromSectionFieldManagedObject:的实现使用NSManagedObject的自定义实体$source子类中的方法,即Choice

Choice的方法似乎不适用于迁移功能,而只是一个香草NSManagedObject

当我尝试使用Choice方法时,我得到一个例外。如果我在调试器中选择po,我会得到类似的结果:

  

< NSManagedObject :0x600000281860> ( entity:Choice ; id:0xd00000000038001a; data:)

然而,出于迁移我通常会看到类似这样的内容:

  

< 选择:0x60800028bdb0> ( entity:Choice ; id:0x6080002225a0; data:{

这是真的如何,还是有一些方法可以在迁移过程中使用实体对象?

可能相关 - 在此迁移期间删除了此特定实体Choice。它在目标托管对象模型中不存在,但确实存在于源托管对象模型中。但是,我不认为是这种情况,因为目标模型中的其他实体类在迁移期间也不可用作该类 - 它们具有类NSManagedObject并且它们的实体方法不可用。

2 个答案:

答案 0 :(得分:2)

这是正确的,您只能在迁移期间访问基本NSManagedObject

  

三阶段迁移

     

迁移过程本身分为三个阶段。它使用源模型和目标模型的副本,其中禁用验证规则,并将所有实体的类更改为NSManagedObject。

来自:Core Data Model Versioning and Data Migration Guide

答案 1 :(得分:1)

Dave's answer澄清说,在迁移过程中,核心数据对象仅可用作NSManagedObject个实例。您无法使用其实体类。

更糟糕的是,如果你使用像mogenerator这样的工具,那么你扩展实体类的任何方便的逻辑都是不可访问的。

糟糕的解决方案

使用NSManagedObject直接对我感到危险。使用[managedObject valueForKey:@"someKey"]是详细的,但更糟糕的是,没有编译器检查您的密钥名称是否正确,因此您可能会要求managedObject没有。也没有编译器检查返回的类型 - 它可以是你可以放入托管对象的任何东西。

稍微好一点是[managedObject valueForKey: NSStringFromSelector(@selector(someKey))]更安全,但可怕的冗长和笨拙,仍然不是 安全 - 许多事情可能会实现方法someKey

您也可以将密钥声明为文字:

NSString *const someKey = @"someKey";
[managedObject valueForKey: someKey];

再次 - 这是更安全,更不容易出错和冗长,但您无法保证托管对象具有someKey

这些方法都不会让我们访问自定义逻辑。

更好的解决方案

我所做的不是为我的托管对象我知道的属性定义protocol。以下是实体ChoiceChoiceType的示例。

@protocol ChoiceProtocol
- (NSSet<id <ChoiceTypeProtocol> > *)choiceTypes;
- (NSNumber *)selected;
- (NSNumber *)order;
@end

@protocol ChoiceTypeProtocol
- (NSNumber *)selected;
- (NSString *)name;
- (NSString *)textCustom;
- (NSNumber *)order;
@end

现在在我的迁移代码中,而不是具有类似于的自定义迁移功能:

- (NSString *)migratedRepresentationOfChoice:(NSManagedObject *)choice;

我有:

- (NSString *)migratedRepresentationOfChoice:(id <ChoiceProtocol>)choice;

在这个函数的主体中,我可以像使用任何常规对象一样使用choice。我输入代码完成后,我得到了正确的语法高亮,如果我调用一个不存在的方法,编译器会抱怨。

我还得到返回类型检查,因此如果我将NSNumber属性selected用作NSStringNSSet,编译器会抱怨。当我输入时,它也会有用,并建议将NSNumber方法作为完成。

逻辑怎么样?

此方法不提供您添加到实体类的逻辑。

在Swift中,您可以使用协议扩展来实现这一目标。

我正在退休这些实体(因此迁移),所以我将实际逻辑函数我需要移动到我的自定义迁移的辅助函数中。例如,choice.orderedChoiceTypes变为[self choiceOrderedChoiceTypes:choice]

将来我可能会避免向NSManagedObject实体添加逻辑。我认为将这些逻辑放在您从托管对象构建的域对象中可能是一个更好的计划。此外,我可能会避免定义实体类,而是在迁移期间通过协议访问NSManagedObject实例。它似乎干净,简单,消除了魔法,并且有利于测试 - 不仅仅是迁移。