将对象添加到 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 个实体,一个 Bill
和 Person
。我有两个关系:
Bill
到 Person
是一种称为“人”的“对多”关系
倒数 - 从 Person
到 Bill
是 'To One' - 称为 'bill'。
Xcode(连同类)生成的结果是:
Bill
:
extension Bill
@NSManaged var people: NSSet?
Person
:
extension Person
@NSManaged var bill: Bill?
这是我编写的将Person
对象添加到Bill
的NSSet
的方法:
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)
NSSortDescriptor 对 Core Data NSSet 对象进行排序的最有效方法
iOS Core Data:使用 Foundation 对象添加属性