如何在获取之前更改托管对象类名称

Dar*_*ski 2 core-data nsfetchedresultscontroller nsfetchrequest nsmanagedobject swift

我有一个使用CoreData的Swift应用程序.我List用class 创建了实体MyAppTarget.List.在.xcdatamodeld文件中正确配置了所有内容.为了从持久存储中获取我的实体,我正在使用NSFetchedResultsController:

let fetchRequest = NSFetchRequest()
fetchRequest.entity = NSEntityDescription.entityForName("List", inManagedObjectContext: managedObjectContext)
fetchRequest.sortDescriptors = [ NSSortDescriptor(key: "name", ascending: true) ]
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: "ListFetchedResultsControllerCache")
Run Code Online (Sandbox Code Playgroud)

并且它像预期的那样工作,MyAppTarget.List在获取时返回对象数组.

但是,我想在另一个目标中使用它进行单元测试.我添加了ListMyUnitTestTarget,所以我可以在单元测试目标中访问它.问题是获取的结果控制器返回MyAppTarget.List对象,而不是MyUnitTestTarget.List对象.为了使List实体可测试,我必须公开它以及我需要使用的所有方法,我想避免这种情况.

我试图更改managedObjectClassName属性NSEntityDescription:

fetchRequest.entity.managedObjectClassName = "MyUnitTestTarget.List"
Run Code Online (Sandbox Code Playgroud)

但它会产生异常:

失败:捕获"NSInternalInconsistencyException","无法修改不可变模型".

文件指出,

[...]一旦使用了描述(当它所属的托管对象模型与持久性存储协调器相关联时),它就不能(实际上不能)被更改.[...]如果需要修改正在使用的模型,请创建副本,修改副本,然后使用旧模型丢弃对象.

不幸的是,我不知道如何实现这个流程.我想知道在获取实体之前是否有办法在运行时更改托管对象类名NSFetchedResultsController

Dar*_*ski 5

我的问题的解决方案非常简单.为了使它工作,我不得不创建一个managedObjectModel的副本,编辑它的实体并NSPersistentStoreCoordinator使用新模型创建.只有在与其所属的模型相关联之前,才可以更改实例managedObjectClassName上的属性.NSEntityDescriptionNSPersistentStoreCoordinator

    let testManagedObjectModel = managedObjectModel.copy() as NSManagedObjectModel
    for entity in testManagedObjectModel.entities as [NSEntityDescription] {
        if entity.name == "List" {
            entity.managedObjectClassName = "CheckListsTests.List"
        }
    }
Run Code Online (Sandbox Code Playgroud)

这也解决了在Swift中对CoreData模型实体进行单元测试的另一个问题.