6
votes

I'm stumped and have not been able to track down any tutorial or document on how best to do this.

Problem: I have two entities, Person and Location. Person can have many locations. I have everything setup properly and can add/remove persons from a tableview, no problem.

The issue I am having is trying to add and remove location after the first one is created -- when the person is inserted for the first time, it also adds a location.

For this purpose, the PersonModel (Person Entity) class has:

class PersonModel: NSManagedObject {

    @NSManaged var Name: String
    @NSManaged var Age: String
    @NSManaged var Location: NSOrderedSet

}

The LocationModel class (Location Entity) has:

class LocationModel: NSManagedObject {

    @NSManaged var State: String
    @NSManaged var Person: PersonModel

}

What is the best way to access and delete items in the Location entity? Should I delete the object from the PersonsModel or via the LocationsModel?

Doing the following:

func deleteObject(rowIndex:NSIndexPath){
  let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
  let managedContext = appDelegate.managedObjectContext!
  let fetchRequest = NSFetchRequest(entityName:"Locations")

  var error: NSError?
  locationsArray = managedContext.executeFetchRequest(fetchRequest,error: &error)!
  managedContext.deleteObject(locationsArray[rowIndex.row] as NSManagedObject)

  var error:NSError? = nil
    if (!managedContext.save(&error)){
        abort()
    }
 }

That doesn't work because it returns all locations, not just the locations for the objects associated with the parent/related Person. There has to be a simple way to do this -- perhaps with predicate?

Can someone help point me in the right direction?

Thanks!

UPDATE: For future folks having the same challenge.

1) Make sure the relationship delete rules are correct. In my case, I wanted to be able to delete the Locations but keep the Person. The delete rules needed to be setup as follows: Location - Delete Rule: Cascade, Person - Delete Rule: Nullify

2) The final code looks like this:

func deleteTrigger(rowIndex:NSIndexPath){

   var personRef: PersonModel = existingItem as PersonModel
   let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
   let managedContext:NSManagedObjectContext = appDelegate.managedObjectContext!
   let fetchRequest = NSFetchRequest(entityName:"Locations")
   let predicate = NSPredicate(format: "Person == %@", personRef)
   fetchRequest.predicate = predicate

   var error: NSError? = nil
   locationArray = managedContext.executeFetchRequest(fetchRequest,error: &error)!

   managedContext.deleteObject(locationArray[rowIndex.row] as NSManagedObject)
   locationArray.removeAtIndex(rowIndex.row)
   tableview.deleteRowsAtIndexPaths([rowIndex], withRowAnimation: UITableViewRowAnimation.Fade)

   if (!managedContext.save(&error)){
     abort()
   }

}
2

2 Answers

3
votes

Using predicates is exactly right. You'd want to set the predicate for the fetchRequest

let predicate = NSPredicate(format: "uniqueKey == %@", "value")
fetchRequest.predicate = predicate

Then you can delete the result

0
votes

How about:

locationsArray = personRef.Location

I think it is much simpler