0

I have two entities Student and Subjects. Student can have multiple subjects. I am getting NSMutableSet object from Student (NSManagedObject)

 let studentSubjects = student?.mutableSetValue(forKey: "subjects")

Now I want to check if a subject is already belongs to that student. For this I am applying filter on NSMutableSet like this

 let assignedSubjects = assignedSubjects.filtered(using: NSPredicate(format: "subject_title == %@", "Science"))

Now I am checking if count is > 0 then do some action else want to assign the subject to the student

 let subjectEntity = NSEntityDescription.entity(forEntityName: "Subject", in: context)

 var subjectObject = NSManagedObject(entity: subjectEntity!, insertInto: context)

 if assignedSubjects.count > 0 {

      if let filteredItem = assignedSubjects.first as? NSManagedObject {

           subjectObject = filteredItem

      }

 }

 if assignedSubjects.count == 0 {
      if let subjectsManagedObject = studentSubjects.allObjects as? [NSManagedObject] {
           if subjectsManagedObject.count > 0 {
                studentSubjects.add(subjectObject)
           } else {                       
                student.setValue(NSSet(object:subjectObject), forKey: "subjects")
           }
           try context.save()
           }
      } else {
           try subjectObject.managedObjectContext?.save()
      }

The problem is It is always inserting new records instead of saving existing records.

Rajat Jain
  • 1,002
  • 1
  • 15
  • 24
  • Do you want to remove the applied filter, so can't you just remove the line where you filter using predicate? I don't get the point. – kamil3 Jul 20 '17 at 15:35
  • I cant remove the line, I have to check if the record already exists or not. – Rajat Jain Jul 20 '17 at 15:46
  • When i m again trying to fetch assigned subjects, I see that the filter is applied – Rajat Jain Jul 20 '17 at 15:48
  • `filter(using: predicate)` mutates the set, but `filtered(using: predicate)` returns a completely new set containing only the items that match the predicate. So use `let filteredSet = assignedSubjects.filtered(using: predicate)`, then test the count of `filteredSet`. – pbasdf Jul 20 '17 at 21:21
  • @pbasdf your suggestion worked for me. Now I am trying to update the existing subject record. if let filteredItem = filteredItems.first as? NSManagedObject { subjectObject = filteredItem } This always insert a new object in the table without relationship – Rajat Jain Jul 21 '17 at 07:35
  • Please can you edit your question to show your revised code? – pbasdf Jul 21 '17 at 07:56

1 Answers1

0

The line which inserts a new object is this one:

    var subjectObject = NSManagedObject(entity: subjectEntity!, insertInto: context)

which is executed regardless of whether the current student already has the relevant subject. Amend your code as follows:

 var subjectObject : NSManagedObject
 if assignedSubjects.count > 0 {
      if let filteredItem = assignedSubjects.first as? NSManagedObject {
           subjectObject = filteredItem

      }
 }
if assignedSubjects.count == 0 {
    let subjectEntity = NSEntityDescription.entity(forEntityName: "Subject", in: context)
    subjectObject = NSManagedObject(entity: subjectEntity!, insertInto: context)
    // I assume, following your example, you want to add a new subject with title "Science"....
    subjectObject.setValue("Science", forKey: "subject_title")

     if let subjectsManagedObject = studentSubjects.allObjects as? [NSManagedObject] {
           if subjectsManagedObject.count > 0 {
                studentSubjects.add(subjectObject)
           } else {                       
                student.setValue(NSSet(object:subjectObject), forKey: "subjects")
           }
           try context.save()
           }
      } else {
           try subjectObject.managedObjectContext?.save()
      }
pbasdf
  • 21,386
  • 4
  • 43
  • 75
  • I don't want to add a new subject. If Science already assigned to student then I want to update some columns of that record. – Rajat Jain Jul 21 '17 at 11:12
  • In that case, just delete the entire second if statement (`if assignedSubjects.count == 0 { ... }`). Update the attributes after `subjectObject = filteredItem`. – pbasdf Jul 21 '17 at 11:19
  • After `subjectObject = filteredItem` when I am trying to save the context with `try context.save()` its inserting new records instead of updating existing record. – Rajat Jain Jul 21 '17 at 11:48