简体   繁体   中英

Inverse Relationship with Core Data Causes Crash when Adding Object to NSSet

I have 2 entities in Core Data, a Bill and Person . I have two relationships:

  • Bill to Person is a 'To Many' relationship called 'people'
  • The inverse - from Person to Bill is 'To One'- called 'bill'.

The result generated by Xcode (along with the classes) are:

Bill :

extension Bill {
    @NSManaged var people: NSSet?
}

Person :

extension Person {
    @NSManaged var bill: Bill?
}

This is the method I've written to add a Person object to the Bill 's 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
    }
}

The custom initialiser for Person is:

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

However, when I add a Person , it crashes at people?.setByAddingObject(person) with the error:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_TtCs21_SwiftDeferredNSArray isEqualToSet:]: unrecognized selector sent to instance 0x7fc7ed875cb0'

When I delete the bill relationship from Person to Bill , it runs fine and the Person is added to the Bill 's 'people' NSSet . I could leave it like this as I don't necessarily need this inverse relationship, but I've read that it is best to have an inverse relationship unless I have a good reason not to. I also face this issue with other relationships in my app, so I would have a lot of relationships without their inverse.

Any ideas what's wrong? Are my relationships incorrect? One Bill can have many Person s, but one Person can only have one Bill .

The solutions I've tried are:

  • Adding this accessor from this answer :

    @NSManaged func addPeopleObject(value:Person)

But I get the error:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSSet intersectsSet:]: set argument is not an NSSet'

  • Creating an NSMutableOrderedSet as suggested by other answers:

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

...but I get the same, original crash message.

  • Unwrapping 'people' - still get the same crash message.

Any help would be much appreciated, thanks.

Ah, I had a similar problem as [this question]. 1 I had a method on Bill called getOwers which had a return type of an array, and this seemed to override the accessor CoreData creates. I changed the method to getOwersArr , and all is fine now. Thanks to @Paulw11 for pointing me in the right direction!

I also have to-many relationships implemented as NSSet . I add/delete objects to the set (without any problems) using code like the following:

let mutableSet = bill.mutableSetValueForKey("people") 

mutableSet.addObject(newPerson)

// (next, save managed object context)

I had a similar issue with iOS 9.3 in a one-to-many relationship.

I fixed it by replacing:

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

with:

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

Basically instead of adding and object to the set use the Inverse relationship.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM