Search code examples
iosswiftcore-datansmanagedobjectcontext

New entity with relationship entity saving causes duplication bug - CoreData Swift


I'm trying to create an Entry object, and add a relationship object to it all in one go but I seem to get a bug with proceeding actions.

The problem I am having is when I create the initial Entry object(1) and add an Exercise object, it works fine. Then when I add a second Exercise object to the Entry object(1) as a separate action, a new Entry object(2) is created instead of using the first one I created. And when I try to add a third/forth/fifth Exercise object to the entry object (distinguished by date), the new exercise is added to the first Entry object(1). Not sure if I'm utilising the NSManagedObjectContext properly which is ultimately contributing to this bug.

Below is how the architecture of it. The Entry object has a OneToMany relationship with Exercise objects.

  • Entry (date) Object <--->>> Exercise Object

Below is the code I am using across various files.

DateModel.swift

class DateModel {

static let sharedInstance = DateModel()
var selectedDate: NSDate! = nil
var context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext

private init() {
    // self.selectedDate = "No date selected"
}

func getEntryForSelectedDate() -> Entry {

    let fetchRequest = NSFetchRequest(entityName: "Entry")
    fetchRequest.predicate = NSPredicate(format: "date = %@", selectedDate)

    var error: NSError?
    entries = self.context!.executeFetchRequest(fetchRequest, error: &error) as! [Entry]

    var entry: Entry? = nil
    if entries.count > 1 {
        entry = entries[0] as Entry
    } else {
        entry = (NSEntityDescription.insertNewObjectForEntityForName("Entry", inManagedObjectContext: self.context!) as? Entry)!
    }

    return entry!
}

func addExerciseToDay(exercise: String) {

    var entryToUpdate = getEntryForSelectedDate()

    var newExercise = NSEntityDescription.insertNewObjectForEntityForName("Exercise", inManagedObjectContext: self.context!) as! Exercise
    entryToUpdate.date = selectedDate
    newExercise.name = exercise
    newExercise.createdAt = NSDate()
    newExercise.entry = entryToUpdate
    entryToUpdate.hasEntry = true

    var error: NSError?
    if !self.context!.save(&error) {
        println("Unresolved error \(error), \(error!.userInfo)")
    }
}
}

ExerciseListViewController.swift

 override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    DateModel.sharedInstance.addExerciseToDay(self.exerciseList[indexPath.row])
    self.navigationController?.popViewControllerAnimated(true)
}

Am I missing something or is there a better way to approach this using Swift?

Any help would be greatly appreciated.

Thanks


Solution

  • if entries.count > 1
    

    is true only if there are (at least) two existing objects. What you probably want is

    if entries.count >= 1
    

    so that a single existing object is updated with the new relationship.