Search code examples
swiftcore-datansmanagedobject

cannot resolve one-to-many relationship


I try to understand coredata. What goes well is adding a Hond and the gewicht. That is neatly put the gewicht in the relationship. But the moment I want to add a extra gewicht later, I run into a problem that I can not do that.

I get to see the following message:

NSManagedObject' is not convertible to 'Hond'

My enitys

This is my code in which I try to add a weight

guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
        let context = appDelegate.persistentContainer.viewContext

        let hondEntity = NSEntityDescription.entity(forEntityName: "Hond", in: context)!
        let hond = NSManagedObject(entity: hondEntity, insertInto: context)

        let gewichtHondEntity = NSEntityDescription.entity(forEntityName: "GewichtHond", in: context)!
        let gewichtHond = NSManagedObject(entity: gewichtHondEntity, insertInto: context)

        let nieuwGewicht = GewichtHond(context: context)
        nieuwGewicht.datum = Date()
        nieuwGewicht.gewicht = Double("38")!
        //gewichtHond.setValue(Date(), forKey: "datum")
        //gewichtHond.setValue(Double("38"), forKey: "gewicht")
        Hond.addToGewichten(gewichtHond) //NSManagedObject' is not convertible to 'Hond

        do {
            try context.save()
            print("Saved")
        } catch let error as NSError {
            print("Could not save. \(error), \(error.userInfo)")
        }

My Hond+CoreDataProperties.swift

    extension Hond {

        @nonobjc public class func fetchRequest() -> NSFetchRequest<Hond> {
            return NSFetchRequest<Hond>(entityName: "Hond")
        }

        @NSManaged public var chipnummer: Int64
        @NSManaged public var dierenarts: String?
        @NSManaged public var geboortedatum: Date
        @NSManaged public var geslacht: Int16
        @NSManaged public var hondId: String?
        @NSManaged public var kleur: String?
        @NSManaged public var naam: String?
        @NSManaged public var orderID: Int16
        @NSManaged public var plaatsVanChip: String?
        @NSManaged public var telefoonnummerDierenarts: String?
        @NSManaged public var vachttype: String?
        @NSManaged public var gewichten: Set<GewichtHond>

    }

    // MARK: Generated accessors for gewichten
    extension Hond {

        @objc(addGewichtenObject:)
        @NSManaged public func addToGewichten(_ value: GewichtHond)

        @objc(removeGewichtenObject:)
        @NSManaged public func removeFromGewichten(_ value: GewichtHond)
/*
       @objc(addGewichten:)
       @NSManaged public func addToGewichten(_ values: NSSet)

       @objc(removeGewichten:)
       @NSManaged public func removeFromGewichten(_ values: NSSet)
*/ 
    }

How do I manage to add an extra gewicht?


Solution

  • The error is a bit misleading. Basically it says that the type of the gewicht relationship is a set rather than a number. This indicates also an interference with the gewicht attribute in GewichtHond.

    To avoid the naming confusion it's highly recommended to name relationships with the entity name of the counterpart and a one-to-one relationship in singular form and a one-to-many relationship in plural form. The one-to-many relationship should be named as gewichten. The type in Swift is supposed to be Set<GewichtHond> not unspecified NSSet

    To add and remove a GewichtHond instance to/from a set at least these two accessor methods are needed in the Hond subclass

    // MARK: Generated accessors for gewichten
    extension Hond {
    
        @objc(addGewichtenObject:)
        @NSManaged public func addToGewichten(_ value: GewichtHond)
    
        @objc(removeGewichtenObject:)
        @NSManaged public func removeFromGewichten(_ value: GewichtHond)
    
    }
    

    Now create a Hond instance and a GewichtHond instance and add the latter to the relationship set

    let hond = NSEntityDescription.insertNewObject(forEntityName: "Hond", into: context) as! Hond
    let gewichtHond = NSEntityDescription.insertNewObject(forEntityName: "GewichtHond" , into: context) as! GewichtHond
    
    hond.addToGewichten(gewichtHond)
    

    Side note: In a NSManagedObject subclass dot notation hond1.datum = Date() is much more convenient (and safer) than KVC method hond1.setValue(Date(), forKey: "datum").