2017-04-25 31 views
0

我将核心数据与mogenerator结合使用来管理一个相当庞大且严重链接的数据对象图。由于过去有些不幸的设计决定(将数据存储为对象中的Transformable),我在执行迁移时遇到了内存问题;迁移非常困难,以至于轻量级技术无法覆盖它,并且自定义迁移尝试将所有内容加载到内存中并导致失败。CoreData + mogenerator - 如何防止中间数据模型中的setValue(forKey:)引用最终数据模型中的实体的'人类'类?

基于Marcus Zarra出色的Core Data book,我已经调整了他的渐进式迁移方法,能够根据轻量级,自定义或“编写自己的”迁移策略混合并匹配连续的迁移过程。我使用它来创建一个中间数据模型,在该数据模型中加载我的“大数据”对象并将其写入磁盘上的外部文件,然后将url保存到该文件中。

基本上,这看起来像这样:

 v1 ----(lightweight)----------> v1.5 --(lightweight)--> v2 
         |        | 
* myData: Transformable | * myData: Transformable? | * myDataUrl: String 
         | * myDataUrl: String  | 

在两间轻质迁移之间,我挂钩一个NSPersistentStoreController至中间模式,取这需要使用fetchLimitfetchBatchSize被改变的对象;将数据写入磁盘上的文件,并使存储在对象本身中的数据无效,在此期间,我定期保存moc并对处理对象进行故障排除。

这很好用..但是......还有另一部分迁移工作不太好,我已经删除了一个关系,并用mogenerated文件的'Human'类中的一个计算属性替换它。 ,即

 v1 ----(lightweight)----------> v1.5 --(lightweight)--> v2 
           |        | 
* myRel ->> [Some object]  | * myRel ->> [Some object]? | (nothing stored here) 
                   computed property `myRel` in the `MyEntity` human class 

按照同样的原则,在“V1.5到V1.5”通过,我移动存储在myRel的信息,不同的级别,并试图设置为nil的关系之后。使用数据模型v2的应用程序仍然使用相同的接口访问myRel中提到的对象,因为我已将它添加为检索移动数据的计算属性。

public var myRel: [Some object] { return ... } 

下面是做这个举动代码:

// Note that since I'm not working on the current data model version in this 
// so-called migration pass, I cannot/should not refer to the real `MyEntity` class that 
// mogenerator generates for me. 
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "MyEntity") 

let objects = try? moc.fetch(fetchRequest) 
objects.forEach { object in 
    // Process objects in `myRel` and move them to a different level 
    let toProcess = ($0.value(forKey: "myRel") as? NSOrderedSet)?.array as? [NSManagedObject]? 

    // ... process ... 

    // Now nullify the original relationship 
    $0.setValue(nil, forKey: "myRel") 
} 

最后一行导致运行时崩溃,显示出通向的最终模型版本生成的“对象”文件mogenerator堆栈跟踪,不这个中间模型

#0 0x0000000100f6885e in MyEntity.myRel.getter at ... 
#1 0x0000000100f68732 in @objc MyEntity.myRel.getter() 
#2 0x000000010ebf7db7 in _PF_Handler_Public_GetProperty() 
#3 0x000000010124f221 in NSKeyValueWillChangeBySetting() 
#4 0x0000000101249798 in NSKeyValueWillChange() 
#5 0x000000010121f618 in -[NSObject(NSKeyValueObserverNotification) willChangeValueForKey:]() 
#6 0x0000000100f47222 in NSManagedObject.setValue<A where ...> (Any?, for : A) ->() at ... 

当然,这是因为崩溃上我的工作不包含在我的计算财产中提到的实体数据模型(那些只是存在于数据模型V2)

此惊喜,我在具有“切片远”的MyEntity类的底层的动态逻辑的希望构造的NSFetchRequest特别是与<NSManagedObject>,但似乎核心数据/夫特推断基于实体名称/描述的运行时类型。有什么办法可以绕过这个吗?

我也尝试过使用setPrimitiveValue,但这会导致我的moc错过更改。我使我对对象所做的更改没有以这种方式保存。

+0

写下这一切有助于看到光线。 我设法解决了这个问题,将中间数据模型中的'myRel'重命名为'myRelOld',并在中间变换中访问那个。由于在迁移到数据模型v2时删除了这种关系,所以这并不重要。 不过,如果任何人都可以给我一个指示,说明为什么Core Data试图使用'当前数据模型'实体而不是中间数据;请注意,我在最新模型中的计算属性未标记为“@ dynamic' /'@ NSManaged';或者只是展示我正在做的事情的新亮点,随时欢迎! – Stavr0s

回答

0

写下这一切有助于看到光线。我设法通过在中间数据模型中将myRel重命名为myRelOld并在中间转换中访问该问题来解决该问题。由于在迁移到数据模型v2时删除了这种关系,所以这并不重要。

相关问题