我正在做一个中等重量的'核心数据迁移。我使用映射模型从一个旧的商店/数据模型迁移到另一个商店和不同的模型(即完全不同的.xcdatamodeld
)文件,并在适用的情况下使用自定义NSEntityMigrationPolicy
对象。 / p>
之前我在对象图上有各种不相关的对象,我现在希望有一个主对象Library
,它可以让我轻松消除所有相关数据(使用Cascade删除规则)
由于我NSEntityMigrationPolicy
子类中的自定义方法,我在迁移过程中遇到了问题:
class LegacyToModernPolicy: NSEntityMigrationPolicy {
func libraryForManager(_ manager: NSMigrationManager) -> Library {
let fetchRequest: NSFetchRequest<Library> = NSFetchRequest(entityName: Library.entity().name!)
fetchRequest.predicate = nil
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "filename", ascending: true)]
fetchRequest.fetchLimit = 1
do {
// will fail here if NSFetchRequest<Library>
let results = try manager.destinationContext.fetch(fetchRequest)
log.info("results: \(results)")
if results.count == 1 {
// can fail here if NSFetchRequest<NSManagedObject>
return results.first! as! Library
} else {
let newLib = Library(context: manager.destinationContext)
return newLib
}
} catch {
log.error("Error fetching: \(error.localizedDescription)")
}
let newLib = Library(context: manager.destinationContext)
return newLib
}
}
将抛出异常,错误消息为:
Could not cast value of type 'NSManagedObject_Library_' (0x6100000504d0) to 'SongbookSimple.Library' (0x101679180).
问题是,为什么会发生这种情况,这有关系吗?因为正在进行迁移,或许它足以使用正确的实体描述返回NSManagedObject
吗?
答案 0 :(得分:1)
原因是在迁移期间,您不应该使用NSManagedObject子类的实例。您需要以NSManagedObject的形式表达所有这些。所以上面的代码必须变成:
class LegacyToModernPolicy: NSEntityMigrationPolicy {
static func find(entityName: String,
in context: NSManagedObjectContext,
sortDescriptors: [NSSortDescriptor],
with predicate: NSPredicate? = nil,
limit: Int? = nil) throws -> [NSManagedObject] {
let fetchRequest: NSFetchRequest<NSManagedObject> = NSFetchRequest(entityName: entityName)
fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = sortDescriptors
if let limit = limit {
fetchRequest.fetchLimit = limit
}
do {
let results = try context.fetch(fetchRequest)
return results
} catch {
log.error("Error fetching: \(error.localizedDescription)")
throw error
}
}
func libraryForManager(_ manager: NSMigrationManager) -> NSManagedObject {
do {
var library: NSManagedObject? = try LegacyToModernPolicy.find(entityName: Library.entity().name!,
in: manager.destinationContext,
sortDescriptors: [NSSortDescriptor(key: "filename", ascending: true)],
with: nil,
limit: 1).first
if library == nil {
let dInstance = NSEntityDescription.insertNewObject(forEntityName: Library.entity().name!, into: manager.destinationContext)
// awakeFromInsert is not called, so I have to do the things I did there, here:
dInstance.setValue(Library.libraryFilename, forKey: #keyPath(Library.filename))
dInstance.setValue(NSDate(timeIntervalSince1970: 0), forKey: #keyPath(Library.updatedAt))
library = dInstance
}
return library!
} catch {
fatalError("Not sure why this is failing!")
}
}}
您可以通过Core Data Migrations here详细了解我的不太有趣的体验。