如何在提取之前更改管理对象类名称 [英] How to change managed object class name before fetching

查看:121
本文介绍了如何在提取之前更改管理对象类名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用CoreData的Swift应用程序。我创建了 List 实体与类 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)




,它的工作方式与预期相同,返回数组 MyAppTarget.List 但是,我想使用它在另一个目标,单元测试。我将 List 类添加到 MyUnitTestTarget ,所以我可以在单元测试目标中访问它。问题是,提取的结果控制器返回 MyAppTarget.List 对象,而不是 MyUnitTestTarget.List 对象。为了使 List 实体可测试,我必须公开所有的方法,我需要使用,我想避免这一点。



我尝试更改 NSEntityDescription

上的 managedObjectClassName

  fetchRequest.entity.managedObjectClassName =MyUnitTestTarget.List

但它生成异常:


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


文档说明


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


不幸的是,我不知道如何实现这个流程。我想知道在使用 NSFetchedResultsController


获取实体之前,是否有一种方法可以在运行时更改管理对象类名。 h2_lin>解决方案

发生这个问题的解决方案很简单。为了使它工作,我不得不创建一个managedObjectModel的副本,编辑其实体,并使用新模型创建 NSPersistentStoreCoordinator 。更改 NSEntityDescription 实例上的 managedObjectClassName 属性只有在它所属的模型与 NSPersistentStoreCoordinator

 让testManagedObjectModel = managedObjectModel.copy()as NSManagedObjectModel 
in testManagedObjectModel.entities as [NSEntityDescription] {
如果entity.name ==List{
entity.managedObjectClassName =CheckListsTests.List
}
}

这也解决了我的其他问题与单元测试CoreData模型实体在Swift。


I have a Swift app that uses CoreData. I created List entity with class MyAppTarget.List. Everything is configured properly in .xcdatamodeld file. In order to fetch my entities from persistent store, I am using 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")

and it works like expected, returning array of MyAppTarget.List objects when fetching.

However, I would like to use it inside another target, for unit testing. I added List class to MyUnitTestTarget, so I can access it inside the unit test target. The problem is that the fetched results controller returns MyAppTarget.List objects, not the MyUnitTestTarget.List objects. In order to make the List entity testable, I have to make it public along with all methods that I need to use and I would like to avoid this.

I tried to change the managedObjectClassName property on NSEntityDescription:

fetchRequest.entity.managedObjectClassName = "MyUnitTestTarget.List"

but it generates exception:

failed: caught "NSInternalInconsistencyException", "Can't modify an immutable model."

The documentation states that

[...] once a description is used (when the managed object model to which it belongs is associated with a persistent store coordinator), it must not (indeed cannot) be changed. [...] If you need to modify a model that is in use, create a copy, modify the copy, and then discard the objects with the old model.

Unfortunately, I don't know how to implement this flow. I wonder if there is a way to change the managed object class name in runtime, before fetching the entities with NSFetchedResultsController?

解决方案

It occurs that solution to my problem was pretty simple. In order to make it working, I had to create a copy of managedObjectModel, edit its entities and create NSPersistentStoreCoordinator with the new model. Changing the managedObjectClassName property on NSEntityDescription instance is possible only before model to which it belongs is associated with NSPersistentStoreCoordinator.

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

This also solves my other problem with unit testing CoreData model entities in Swift.

这篇关于如何在提取之前更改管理对象类名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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