Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does Core Data Nullify rule update relations?

What I have and want:

I have a one-to-many relationship A <--->> B (the to-many part is ordered).

  • When deleting A all B's with a relation to A should be deleted as well, so the deletion rule for A's relation to B is set to cascade -> Works fine
  • When deleting B only the relationship back to A should be cleared, so the deletion rule for B's relation to A is set to nullify -> Doesn't work (only after a delay)

Description of the problem:

So I have the exact same problem as stated in this question "Core Data Nullify rule doesn't work?": I delete a B that has a relation to an A and immediately after that, I count the number of remaining B's, that A has a relation with and it is the same as before. The accepted answer in that question was to use cascade instead of nullify since what nullify does is:

Nullify sets the pointer to null when the object is deleted. If you have an array of pointers it doesn't remove it, it just sets it to null.

I see 2 issues with that answer:

  1. I am pretty sure cascade is the wrong rule in this case, because it would also delete A when deleting B, which is not what I want to achieve. (I tried it nevertheless and the result was what I expected: A was also deleted).
  2. A collection can not have null as one of its elements, except one uses the NSNull singleton. So I doubt that this is what the nullify rule does.

After experimenting a bit I found out that, if I delete an instance of B it is deleted immediately but the relation to A is not cleared immediately but only after a little delay:

// Method is called by pressing a button
-(void)removeLastBOfA:(A *)instanceOfA
{
    // Prints 4
    NSLog(@"fetch all b's count before:%d", [context fetchAllBs].count);
    // Prints 4
    NSLog(@"A's relation to B count before: %d", instanceOfA.relationToB.count);

    [context deleteObject:[instanceOfA.relationToB lastObject]];

    // Prints 3
    NSLog(@"fetch all b's count after:%d", [context fetchAllBs].count);
    // Prints 4, but should be 3. Last Object of A's relationToB is still the object that was deleted
    NSLog(@"A's relation to B count after: %d", instanceOfA.relationToB.count);

}

Now when pressing the button to call the method above again without doing anything in between, suddenly the relation is updated and "A's relation to B count before: 3" is printed. So the nullify deletion rule does work as I want it to, but with a little delay.

Questions:

  1. Are the 2 issues I stated valid?
  2. Why does nullify only update the relation after a delay and what is that delay? Or at which point do the relations get updated after deleting a NSManagedObject?
like image 673
Andre Guerreiro Avatar asked Feb 12 '13 17:02

Andre Guerreiro


1 Answers

Yes you are right. The answer is not correct. Regarding to second point. The method -deleteOdject does not delete object as you expected it just marks object as deleted. To accomplish deletion you need to save managed object context and then you will see that nullify rule works as expected. If you do not want to save context at this moment you could follow two ways:

  1. Explicitly delete relationship:

    NSManagedObject* objectToDelete = [instanceOfA.relationToB lastObject];
    [context deleteObject:objectToDelete];
    NSMutableSet* relationships = [instanceOfA mutableSetValueForKey:@"relationToB"];
    [relationships removeObject:objectToDelete];
    
  2. Ask context to process its future changes (it means calculate changes caused by your deletion):

    [context processPendingChanges];
    

In your example:

[context deleteObject:[instanceOfA.relationToB lastObject]];
[context processPendingChanges];
// Prints 3
NSLog(@"fetch all b's count after:%d", [context fetchAllBs].count);
NSLog(@"A's relation to B count after: %d", instanceOfA.relationToB.count);

After that you will see expected result.

NSManagedObjectContext does -processPendingChanges by itself at the end of run loop or when performing -save:, so that is why you see some delay.

Hope it helps.

like image 171
Mark Kryzhanouski Avatar answered Nov 09 '22 14:11

Mark Kryzhanouski