ios - 核心数据迁移: Could not cast value of type 'NSManagedObject_MyType' to 'MyModule.MyType'

标签 ios swift core-data migration

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

以前,我在对象图上有各种不相关的对象,现在我想要一个主对象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
  }
}

会抛出异常,错误信息为:

无法将“NSManagedObject_Library_”类型的值 (0x6100000504d0) 转换为“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!")
    }
}}

您可以详细了解我在核心数据迁移方面的不那么有趣的经历 here .

关于ios - 核心数据迁移: Could not cast value of type 'NSManagedObject_MyType' to 'MyModule.MyType' ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46174543/

相关文章:

swift - removeObserver() 是否移除所有观察者?

iOS:RESTKit 与 CoreData 同步数据

ios - 保留读取的推送通知

ios - 具有相同 xib 的两个不同的 UITableViewCell

iphone - UIWebView中是否需要用 "loadHTMLString"定义<head>和<body>?

iOS 禁用 NavigationController 后退按钮的动画

ios - 从具有多个部分的 TableView 继续

ios - 项目库中的Apple Mach-O链接器错误重复符号

ios - Coredata 谓词,用于匹配列中具有任意出现顺序的多个单词的字符串

iOS DOM 树不代表屏幕上的对象