views:

30

answers:

1

Hello,

I think I have a problem, maybe linked to a retain cycle in Core-Data. The code is a follow, where self.image is also a NSManagedObject:

- (void)setImage:(UIImage*)image1 andThumbnail:(UIImage*)image2
{
    self.image.data = UIImageJPEGRepresentation(image1, 0.85); // This is autoreleased
    self.thumbnail = UIImageJPEGRepresentation(image2, 0.85); // This is autoreleased
}

Apparently, the "self.image.date =" has one retain that is never released (and I think that it is between self.image and self). Because of that the self object will never be released and hence the leak.

EDIT: so basically I have the same problem as here: https://devforums.apple.com/message/246219#246219 I use exactly the same structure where the self in the previous code corresponds to the Bar in the given link. I also have the same view controller structure. However, the refreshObject doesn't help.

I tried to use the NSManagedObjectContext refreshObject method to break the retain cycle (as suggested in Apple documentation). It has no influence on the retainCount. I'm probably not using it the right way but I can't find much information about it. If I use NSManagedObjectContext:reset: I get a crash in the root view controller when I come back to it.

Thanks!

+2  A: 

You should not interfere with the managed object context's management of the managed objects memory.

If self.image above is a managed object and you have not written custom accessors then you have no memory management concerns from it. Any attempt to manage the context's memory manually will almost always cause more problems than it solves.

Retain counts tell you nothing except in the simplest and smallest of command line apps. Once you use frameworks like Core Data, the behind the scenes retention is so complex that the retain count often bears no relationship to what happens in your own code.

Apparently, the "self.image.date =" has one retain that is never released (and I think that it is between self.image and self). Because of that the self object will never be released and hence the leak.

This will not happen. You do not have to kill all objects in an instance's retained attributes before killing the instance itself. If that was true, you couldn't kill an instance that shared an attribute object with a 3rd object. If they were non-managedObject instances, the self.image object can exist long after the self object dies. Only the enforcement of the entity graph by the context makes them behave different and that has nothing to do with memory management.

If you see a mysterious retain count of 1 on a managed object, that is the retain put on the object by the managed object context. As long as the context believes the managed object must exist in the entity graph, it will never release the object.

If the leak is in the Core Data stack at all, your problem is most likely in the entity graph between the self entity and the self.image entity. The entity graph is preventing one or the other from being deleted most likely by a deny or a required relationship.

TechZen
I don't delete entities. Actually I kind of solved the problem by using the refreshObject: on the self.image. Without that, I think I keep having a retain cycle between self and self.image just due to the mutual relationship.
Kamchatka
I'm not sure what your issue is but merely saving an NSData instances into a managed object shouldn't cause leaks. This is a very common operation.
TechZen