首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >一对一关系的值类型不可接受:属性=“用户”;所需类型=用户;给定类型=用户;

一对一关系的值类型不可接受:属性=“用户”;所需类型=用户;给定类型=用户;
EN

Stack Overflow用户
提问于 2016-11-15 05:18:43
回答 3查看 824关注 0票数 11

我的核心数据出现了连线问题。使用iOS 10中的Swift3,我每次获取或存储数据时都会获得托管对象上下文

代码语言:javascript
复制
 func getContext () -> NSManagedObjectContext {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    return appDelegate.persistentContainer.viewContext
}

在我的应用中,我有两个实体'User‘和'Ledger’。我想将一个账本分配给一个用户,但一个用户可以有多个账本。因此,我有一个可以显示users的UserTableView和一个可以创建user的UserViewController类。我对账本也是一样。创建账本时,我还会得到一个所有用户的列表,从中选择一个用户,并将哪些用户分配给账本,反之亦然。

当像上面提到的那样保存时,我得到了错误

代码语言:javascript
复制
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for to-one relationship: property = "user"; desired type = User; given type = User;

我的数据模型如下所示:Data Model

我们非常感谢您的帮助:)

EN

回答 3

Stack Overflow用户

发布于 2017-07-27 22:06:45

我也有同样的问题。在我的例子中,它是在我运行单元测试时发生的。在这种情况下,内存中同时有两个核心数据堆栈,一个用于应用程序控制,另一个用于我正在运行的单元测试。

解决这个问题的第一个线索是在设置relationship属性之前设置一个断言,以确保我正在设置的对象的实体类型与关系的预期实体类型相同。它们应该是相同的,但在我的例子中却不是。

在我的例子中,我有一个与Player具有一对一关系的MatchRequest,称为"initiator“。因此,我的断言如下所示:

代码语言:javascript
复制
    let player = try Player.findLocal(for: matchRequest.initiator, in: moc, createIfMissing: true)
    let expectedEntity = self.entity.relationshipsByName["initiator"]!.destinationEntity!
    assert(player!.entity === expectedEntity, "Player returned doesn't have the same entity type")
    self.initiator = player

上面的断言失败了,我怀疑这与Core Data使用的导致参数异常的断言相似。

在检查Player.entity()时,它将返回导致失败的同一实体实例。

我认为问题的根源是核心数据正在为实体设置一些静态属性,这些属性将在核心数据堆栈之间不正确地共享。当从一个堆栈调用时,调用MyManagedObject.entity()将正常工作,而从另一个堆栈调用则不会。

因此,为了解决这个问题,当我创建要放入关系中的播放器对象时,我使用较旧的NSEntityDescription.insertNewObject(...) API而不是较新的MyManagedObject(context:)构造函数来获取实体。这可确保为给定的托管对象上下文使用正确的实体。

所以,重述一下:

代码语言:javascript
复制
// SOMETIMES FAILS if you have more than one core data stack:
result = Player(context: managedObjectContext)

// ALWAYS WORKS:
result = NSEntityDescription.insertNewObject(forEntityName: "Player", into: managedObjectContext) as? Player
票数 9
EN

Stack Overflow用户

发布于 2019-01-29 21:17:36

我也有同样的问题,但我非常确定我没有像上一个答案那样有2个核心数据堆栈。

最后,我意识到我已经使用lazy关键字初始化了对NSStoreCoordinator的引用、视图上下文和背景上下文。我也有一堆代码在后台线程中做一些繁重的提升,并使用所述堆栈进行保存。

苹果公司的文档说:“如果一个标有惰性修饰符的属性被多个线程同时访问,并且该属性还没有被初始化,就不能保证该属性只被初始化一次。”

所以,这个不幸的场景是导致这个错误的另一种方式。解决方案:确保在核心数据堆栈中不要lazy任何东西,特别是在执行大量后台/前台线程工作时。

我希望它能在未来帮助一些人。如果你在这里,对你未来的开发者说:祝你好运。

票数 1
EN

Stack Overflow用户

发布于 2020-12-04 09:42:33

我也遇到了同样的问题。我认为@Chris已经清楚地给出了原因。进行测试时,内存中有多个实例。

解决方案是将NSPersistentContainer初始化部分移到setUpWithErrortearDownWithError中。

在下面的示例中,CoreDataManager负责NSPersistentContainerinit

代码如下:

之前的

代码语言:javascript
复制
class FooTests: XCTestCase {
    var manager: CoreDataManager = CoreDataManager()
}

之后的

代码语言:javascript
复制
 class FooTests: XCTestCase {

        var manager: CoreDataManager?

        override func setUpWithError() throws {
             manager = CoreDataManager(inMemory: true)
        }

        override func tearDownWithError() throws {
             manager = nil
        }

    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40597981

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档