Custom To-Many Relationship Accessor Methods not called when delete rule is executed

327 Views Asked by At

I have a problem I don't understand..

I have a simple Core Data Model with Collection's and CD's. Every CD can be added to multiple Collections, so I added an intermediate object to make this possible. (edit: This is a simplification of my DataModel. The intermediate object is needed for nesting collections in collections)

So when a CD is added to a Collection it looks like this: (IM is the intermediate object)

|==========|         |==========|         |==========|
|          |         |          |         |          |
|Collection|=========|   IM     |=========|    CD    |
|          |         |          |         |          |
|==========|         |==========|         |==========|

I have set the delete rules so that if a CD is deleted by the user, the IM object is cascade deleted and with deleting the IM object, the collection property nilled. That is behaving like I wanted it. No leftovers in the Database.

But the weird thing is that if I override the custom to-many relationship accessor method for removing the IM from the Collection (which I assumed would be called), nothing happens.

I am using what Apple provides in their Core Data Programming Guide. the link

For Single object:

- (void)removeEmployeesObject:(Employee *)value
  {
      NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
      [self willChangeValueForKey:@"employees"
            withSetMutation:NSKeyValueMinusSetMutation
            usingObjects:changedObjects];
      [[self primitiveEmployees] removeObject:value];
      [self didChangeValueForKey:@"employees"
            withSetMutation:NSKeyValueMinusSetMutation
            usingObjects:changedObjects];
}

for removing multiple objects:

- (void)removeEmployees:(NSSet *)value
  {
      [self willChangeValueForKey:@"employees"
            withSetMutation:NSKeyValueMinusSetMutation
            usingObjects:value];
      [[self primitiveEmployees] minusSet:value];
      [self didChangeValueForKey:@"employees"
            withSetMutation:NSKeyValueMinusSetMutation
            usingObjects:value];
}

(taken from the pdf, they use Employee as a to-many relation here)

But these methods are not called when the delete rules are executed!

So my Question: The IM object is cascade deleted, but these methods are not used. How can I detect this deletion action that Core Data does?

Is there another way?

I want to know this because I want to set a "dirtyFlag" on all Collection's that have been changed, so I can update some things for those objects. (other properties, won't explain here)

(KVO on the object would be useless. I can't go observing the complete DataBase, can I?. Or should the Collection object KVO itself for this property?)

Hope someone can help me!

2

There are 2 best solutions below

1
On BEST ANSWER

Alternatively, you could implement -prepareForDeletion in your IM managedObject subclass.
-prepareForDeletion is automatically called by Core Data on a managedObject just before it's deleted from it's managedObjectContext.

When -prepareForDeletion is called, all relationships are still available and you could send a custom -willDeleteIntermediateObject: message to all of the containing Collections, passing self as a parameter.

You could then implement -[Collection willDeleteIntermediateObject:] to check if it's the last IM object it contains and if so, make it delete itself from it's managedObjectContext.

// IM.m
- (void)prepareForDeletion {
    [super prepareForDeletion];

    for (Collection *collection in self.collections) {
        [collection willDeleteIntermediateObject:self];
    }
}

// Collection.m
- (void)willDeleteIntermediateObject:(IM *)im {
    if (self.intermediateObjects.count == 1 && [self.intermediateObjects.containsObject:im]) {
        [self.managedObjectContext deleteObject:self];
    }
}
4
On

Are you modifying your data using fetched properties? The mutable collection accessor methods won't be called in that case.

If you want to set the dirty flag on literally every deletion, it might be a better pattern to simply register for the NSManagedObjectContextObjectsDidChangeNotification notification. Use the NSDeletedObjectsKey key to get the deleted objects out of the userInfo dictionary. You can set the dirty flag on their collections at that time.