22

After creating a data model in Xcode, it's throwing the following error for each of the object relationships:

Consistency Error:
Setting the No Action Delete Rule on [object relationship] is an advanced setting

What is Xcode trying to tell me, and how should I respond?

Dan
  • 1,677
  • 5
  • 19
  • 34

2 Answers2

47

Core Data uses inverse relationships and delete rules to keep the object graph consistent

Let's say you have A.foo <1—1> B.bar and do a.foo = b. This automatically (effectively) performs b.bar = a.

Now let's say you [b delete]. With the "nullify" rule, effectively does b.bar.foo = nil. With "cascade", it does [b.bar delete]. With "no action", it does nothing; a.foo is now a "dangling Core Data object reference".

It's not really a dangling pointer; standard memory management rules mean that b will still exist in memory while a points to it (until a turns into a fault), but a.foo will forever refer to a deleted object, which raises an exception when you try to access its properties. I'm not sure what happens when you save and re-fetch a either.

With a many-to-many relationship, it gets more complicated. Implementation details: The relationship appears to be "owned" by one of the entities, and is only saved when that entity is saved (I hit this bug when trying to set up a relationship across different MOCs: the MOC that saved didn't own the updated entity, so the relationship was never saved). Clearly when you delete both a and b, the relationships should also be removed, so one assumes that the relationship disappears only one of them is removed (but you don't know which one!).


You probably want Nullify or Cascade. I never use Cascade because I can never remember which direction the cascading happens in.

tc.
  • 33,468
  • 5
  • 78
  • 96
  • 1
    +1 For concise description. I would add that I usually use Nullify but have also found Cascade to be very helpful. If you use No Action, then you should probably be implementing -prepareForDeletion on your NSManagedObject subclasses. – westsider Apr 12 '11 at 03:32
  • 1
    In terms of remembering which direction the cascade happens, it helps to think of the entity you've selected in the data model as the source, and the destination of the relationship as the target. When you set nullify or cascade, you are specifying the action that the source will take when the source is deleted - i.e. above you have set nullify or delete on the relationship b.bar. In the case of nullify, the action is to look for an inverse relationship on the target and set it to null. So nullify depends on inverse existing on the target, cascade does not. – Colin Sep 20 '11 at 15:28
  • 1
    Hey, suppose a one-to-many relantionship! the one of many should not nullify the ONE object! It might really perform no action! More over if I set Nullify I can't fetch this object from data base though it is there! – Stas Aug 01 '13 at 16:19
  • @Stas If you use Nullify and remove one of the "many" objects, it should remove it from the *set* of related objects on the "one" object. Bad Things would happen if it performed "no action". – tc. Aug 25 '13 at 02:36
  • @tc it doesn't matter what it "should", what it does is nullify the whole set which is catastrophic. – Hogdotmac Sep 04 '20 at 09:04
17

Deny If there is at least one object at the relationship destination, then the source object cannot be deleted. For example, if you want to remove a department, you must ensure that all the employees in that department are first transferred elsewhere (or fired!) otherwise the department cannot be deleted.

Nullify Set the inverse relationship for objects at the destination to null. For example, if you delete a department, set the department for all the current members to null. This only makes sense if the department relationship for an employee is optional, or if you ensure that you set a new department for each of the employees before the next save operation.

Cascade Delete the objects at the destination of the relationship. For example, if you delete a department, fire all the employees in that department at the same time.

No Action Do nothing to the object at the destination of the relationship. For example, if you delete a department, leave all the employees as they are, even if they still believe they belong to that department.

Daniel
  • 1,473
  • 3
  • 33
  • 63
  • I have this problem , and I understand the rules just like you described them , but my problem is like this: If I delete an employer , I don't want to delete the entire department. Then , I should use Deny , I know. But even if I delete the last employer in the department , I still don't want the department to be deleted from the entire list of departments. In this case...I have to get over those warnings , right? – George Oct 17 '12 at 11:02
  • 1
    Which warnings? Use "Nullify" at the Employe's relationship to the department. – Daniel Oct 17 '12 at 13:10
  • This answer doesn't really help the question but simply reiterates the rules. – p0lAris Mar 30 '15 at 23:58