将对象添加到 NSSet 时与 Core Data 的反比关系导致崩溃

Posted

技术标签:

【中文标题】将对象添加到 NSSet 时与 Core Data 的反比关系导致崩溃【英文标题】:Inverse Relationship with Core Data Causes Crash when Adding Object to NSSet 【发布时间】:2016-04-27 00:30:25 【问题描述】:

我在 Core Data 中有 2 个实体,一个 BillPerson。我有两个关系:

BillPerson 是一种称为“人”的“对多”关系 倒数 - 从 PersonBill 是 'To One' - 称为 'bill'。

Xcode(连同类)生成的结果是:

Bill:

extension Bill 
    @NSManaged var people: NSSet?

Person:

extension Person 
    @NSManaged var bill: Bill?

这是我编写的将Person 对象添加到BillNSSet 的方法:

class Bill : NSManagedObject 
...

func addPersonToBill(contact : CNContact)

        let entDesc = NSEntityDescription.entityForName("Person", inManagedObjectContext: managedObjectContext())

// Create Person object with custom initialiser
        let person = Person(contact: contact, entity: entDesc!, insertIntoManagedObjectContext: managedObjectContext())
        print("Got person")

        people = people?.setByAddingObject(person) // CRASHES HERE
    

Person 的自定义初始化程序是:

init(contact : CNContact, entity : NSEntityDescription, insertIntoManagedObjectContext context : NSManagedObjectContext?)
        super.init(entity: entity, insertIntoManagedObjectContext: context)
   // I set other properties here using info from the CNContact
    

但是,当我添加 Person 时,它会在 people?.setByAddingObject(person) 处崩溃并出现以下错误:

*** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[_TtCs21_SwiftDeferredNSArray isEqualToSet:]: 无法识别的选择器发送到实例 0x7fc7ed875cb0'

当我将bill 关系从Person 删除到Bill 时,它运行良好,并且Person 被添加到Bill 的“人”NSSet。我可以这样保留它,因为我不一定需要这种反比关系,但我读过最好有一个反比关系,除非我有充分的理由不这样做。我的应用程序中的其他关系也面临这个问题,所以如果没有它们的逆关系,我会有很多关系。

任何想法有什么问题吗?我的关系不正确吗?一个Bill 可以有多个Person,但一个Person 只能有一个Bill

我尝试过的解决方案是:

从this answer添加这个访问器:

@NSManaged func addPeopleObject(value:Person)

但我得到了错误:

由于未捕获的异常而终止应用程序 'NSInvalidArgumentException',原因:'*** -[NSSet intersectsSet:]: set 参数不是 NSSet'

按照其他答案的建议创建NSMutableOrderedSet

let mutPeople = NSMutableOrderedSet(array: (people?.allObjects)!) mutOwers.addObject(person) people = NSSet(array:mutPeople.array)

...但我收到相同的原始崩溃消息。

解开“人” - 仍然会收到相同的崩溃消息。

任何帮助将不胜感激,谢谢。

【问题讨论】:

尝试解开您的 people 属性。类似if let people = self.people as? NSSet self.people = people.setByAddingObject(person) else self.people = NSSet(object:person) @Paulw11 我得到同样的错误:/ 如果设置断点,看看people是什么类?异常表明 Swift 将其转换为 SwiftDeferredNSArray 而不是集合 @Paulw11 嗯...当我打开 people 并打印它的 dynamicType 它说它是 _NSFaultingMutableSet,所以它不是 NSArray 就像错误似乎说的那样 我对您为什么必须编写代码来管理这些关系很感兴趣。只需分配 person.bill=bill 就可以了 【参考方案1】:

啊,我遇到了与 [this question] 类似的问题。1 我在Bill 上有一个名为getOwers 的方法,它的返回类型为数组,这似乎覆盖了CoreData 创建的访问器。我将方法更改为getOwersArr,现在一切正常。感谢@Paulw11 为我指明了正确的方向!

【讨论】:

【参考方案2】:

我也有以NSSet 实现的多对多关系。我使用如下代码向集合中添加/删除对象(没有任何问题):

let mutableSet = bill.mutableSetValueForKey("people") 

mutableSet.addObject(newPerson)

// (next, save managed object context)

【讨论】:

【参考方案3】:

我在 ios 9.3 的一对多关系中遇到了类似的问题。

我通过替换来修复它:

group.addToTeams(team) // Crashes on iOS 9.3

与:

team.group = group // This will correctly add team to the set without crashing

基本上使用反向关系而不是添加和对象到集合中。

【讨论】:

以上是关于将对象添加到 NSSet 时与 Core Data 的反比关系导致崩溃的主要内容,如果未能解决你的问题,请参考以下文章

iOS NSArray, NSSet 与 Core Data Query (Fetch Request)

iOS Core Data - 将相关数据添加到实体

NSSortDescriptor 对 Core Data NSSet 对象进行排序的最有效方法

iOS Core Data:使用 Foundation 对象添加属性

将 `lastModified` 记录添加到 Core Data 托管对象

iPhone Core Data 对象添加到 NSMutableArray