Search code examples
swiftcore-datainitializationnsmanagedobjectnsmanagedobjectcontext

How do I initialize a new NSManagedObject and set a relationship to another NSManagedObject within a single managed object context?


I'm creating a new NSManagedObject and trying to establish a relationship to another NSManagedObject but I get this error:

Illegal attempt to establish a relationship 'lift' between objects in different contexts

I know why this is happening - I just don't know how to fix it.

I'm calling this function to create the new object:

func createNewLiftEvent() -> LiftEvent {
    let entity = NSEntityDescription.entityForName("LiftEvent", inManagedObjectContext: moc!)
    let newLiftEvent = LiftEvent(entity: entity!, insertIntoManagedObjectContext: moc)

    return newLiftEvent
}

My LiftEvent instance is setting its own values at initialization. In awakeFromInsert, three helper methods are called and they use a class called LiftEventDataManager (dataManager) which is of course what's creating the second managedObjectContext I don't want:

override func awakeFromInsert() {
    super.awakeFromInsert()

    let defaultUnit = getDefaultWeightUnit()  // returns an NSManagedObject
    self.weightUnit = defaultUnit

    let defaultLift = getDefaultLift() // returns an NSManagedObject
    self.lift = defaultLift

    let defaultFormula = getDefaultFormula() // returns an NSManagedObject
    self.formula = defaultFormula

    self.maxAmount = 0.0
}

This is an example of one of those helper methods:

func getDefaultFormula() -> Formula {
    let formulasArray = dataManager.fetchSelectableFormulas() // this is what creates a new managedObjectContext
    let defaultFormula = NSUserDefaults.formula().rawValue
    formula = formulasArray[defaultFormula]
    return formula
}

The createNewLiftEvent() function is in the LiftEventDataManager class along with the methods like the .fetchSelectableFormulas() method called within the helper function above.

Apple's Core Data Programming guide doesn't say anything about this particular problem and I haven't found any threads on SO that address the problem of multiple context at initialization time.

How can I create the new LiftEventObject in 'context A' and fetch those other managed objects and get them into 'context A' so I can set the relationships?


Solution

  • One option could be to pass around your original LiftEvent object and have your helper methods do their thing using that LifeEvent's managedObjectContext (all managed objects have a reference to their context, so you can make use of that fact).

    (May not apply, but FYI, be careful if threads come into play. You may need to also use performBlockAndWait)