Question

I have a Recipe object in Core Data that can hold a Photo object. The latter contains a NSData property for the image and some utility properties.

I'm running into an inconvenience when I change the Photo of a Recipe:

recipe.photo = [Photo insertIntoContext: ctxt];

If recipe.photo was nil, everything works as expected. However, if it had a previous instance of Photo, that one becomes "garbage", with a nil recipe property (inverse relationship of photo) and causes an exception when saving (recipe isn't optional in my model).

Therefore, I end up having to do something like this:

if(!recipe.photo){
   [ctxt deleteObject:recipe.photo);
}
recipe.photo = [Photo insertIntoContext: ctxt];

This looks awfully like manual memory management where I have to make sure the "orphaned" Photo is properly deleted.

There's gotta be a better way. What am I doing wrong?

Was it helpful?

Solution

Your solution works and you have the approach correct. Core Data will not automatically delete a dangling child. You will need to explicitly delete it. However, the "where" comes into question.

If you really always want to delete the existing child before adding a new one like this then I would handle it in the subclass of the parent object in the set accessor. This will allow you to check for equality, etc. before performing the delete. That would also remove this maintenance work from your (presumably) view controller.

Update

OK, thanks. So I should create a custom setter with setPrimitiveValue & friends?

Correct. You will also want to have the KVO methods in place as well (-willChangeValueForKey: and -didChangeValueForKey:) so that your accessor is doing the right thing.

OTHER TIPS

Another, simpler solution is to set the "Delete rule" of the relationship to "Cascade". Then if an object is deleted, the object(s) at the other end of the relationship is/are automatically deleted.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top