Search code examples
iosswiftcore-datansfetchedresultscontroller

Update NSFetchedResultsController object when relationship object was deleted


Let's say I have objects in my FetchedResultsController. The objects have a relationship to another entity called Category. This can be nil, if no category was set by user, or the selected category. The user can delete and create categories whenever he wants.

However, when a category was deleted, the objects who had the specific category, instead of having nil as category property, it have the specific category, which doesn't exist anymore, giving me an error.

How can I update my frc objects so that when a category was deleted, every other object who had the category property set as the deleted category, sets the current category as nil.

This is how I save data in frc:

   func save(sumText: String, dataDescription: String, dataColor: UIColor, category: Categories?, type: String, completion: (_ finished: Bool) -> ()) {
        let budget = NSEntityDescription.insertNewObject(forEntityName: "Budget", into: managedObjectContext!) as! Budget

        budget.dataSum = sumText
        budget.dataDescription = dataDescription
        budget.dataColor = dataColor
        budget.dateSubmitted = Date()
        budget.dateSection = formatDate(date: Date())
        budget.type = type

        if let cat = category {
            budget.category = cat
        }


        do{
            try managedObjectContext?.save()
            print("Succesfully saved data")
            completion(true)
        } catch {
            debugPrint("Could not save \(error.localizedDescription)")
            completion(false)
        }
    }

This is how I delete a category:

    let deleteAction = SwipeAction(style: .destructive, title: "Sterge") { (action, indexPath) in

        guard let managedContext = appDelegate?.persistentContainer.viewContext else { return }

        managedContext.delete(userCategories[indexPath.row])

        do {
            try managedContext.save()
        } catch {}

        self.fetchCoreDataObject()
        tableView.reloadData()

    }

So when I delete the categories I have to update all the objects with that category to be set as nil, but I don't know how.

The relationship


Solution

  • All you need to do is to specify the delete rule as Nullify.

    enter image description here

    When you use a Nullify delete rule, on deleting the object all other object having its reference as a part of their relationship gets initialized to nil as you expected. You don't need to write code for that.

    Issue in your code now:

    Looking at the model you posted, I can see that Budget Entity has a Relationship (one to one) with Categories Entity by name category. So now if you simply select the category relationship and set the delete rule to Nullify on deleting the Budget Category will have its reference as nil But thats not what you want.

    First of all when you name a relationship between the entity thumb rule is that Entity Name1 -> RelationShip name -> Entity Name2 should make a statement and explain the relationship explicitly.

    Example: Budget isOfType Category

    Inverse can be : Category is usedBy Budget.

    But usedBy cant be one to one relationship as you have shown. Category can be used in multiple Budgets. You dont wanna create a separate category for each Budget entity do you ?

    enter image description here

    Lets finally specify delete rule. When you delete a Category all the isOfType reference in Budget should be set to nil correct. So select the Category Entity, highlight usedBy relationship and set delete rule to Nullify

    enter image description here

    Finally if user delete the Budget, Categories should be left unaltered so Select Budget, Highlight isOfType and set delete rule to

    enter image description here

    Hope this helps :)