核心数据迁移:无法将类型为"NSManagedObject_MyType"的值转换为"MyModule.MyType" [英] Core Data Migration: Could not cast value of type 'NSManagedObject_MyType' to 'MyModule.MyType'

查看:62
本文介绍了核心数据迁移:无法将类型为"NSManagedObject_MyType"的值转换为"MyModule.MyType"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做中等重量"的核心数据迁移.我正在使用映射模型从一个旧式存储/数据模型迁移到另一个存储和不同模型(即完全不同的.xcdatamodeld)文件,并在适用的情况下使用自定义NSEntityMigrationPolicy对象.

以前,在对象图上我有各种各样不相关的对象,现在我想要一个主对象Library,使我能够轻松擦除所有关联数据(使用Cascade删除规则). /p>

由于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吗?

解决方案

原因是在迁移期间,您不应使用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上的不愉快经历的更多信息

An exception will be thrown, and the error message is:

Could not cast value of type 'NSManagedObject_Library_' (0x6100000504d0) to 'SongbookSimple.Library' (0x101679180).

The question is, why is that happening, and does it matter? Because a migration is happening, perhaps it's enough to return the NSManagedObject with the correct entity description ?

解决方案

The reason is that during migration, you should not be using instances of NSManagedObject subclasses. You need to express all of these in the form of NSManagedObject. So the code above must become:

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!")
    }
}}

You can read more about my less-than-fun experiences with Core Data Migrations here.

这篇关于核心数据迁移:无法将类型为"NSManagedObject_MyType"的值转换为"MyModule.MyType"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆