Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data with SWIFT: How to delete object from Relationship entity?

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()
   }

}
like image 460
Mavro Avatar asked Feb 06 '15 21:02

Mavro


People also ask

How do I delete an object in Core Data?

Table views have a built-in swipe to delete mechanic that we can draw upon to let users delete commits in our app. Helpfully, managed object context has a matching delete() method that will delete any object regardless of its type or location in the object graph.

What is delete rule in Core Data?

A delete rule defines what happens when the record that owns the relationship is deleted. Select the notes relationship of the Category entity and open the Data Model Inspector on the right. By default, the delete rule of a relationship is set to nullify. Core Data supports four delete rules: No Action.

What is Persistentcontainer in Core Data?

NSPersistentContainer simplifies the creation and management of the Core Data stack by handling the creation of the managed object model ( NSManagedObjectModel ), persistent store coordinator ( NSPersistentStoreCoordinator ), and the managed object context ( NSManagedObjectContext ).


1 Answers

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

like image 72
d2burke Avatar answered Oct 04 '22 16:10

d2burke