Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Objective C why are my core data objects never being deallocated?

I am having a lot of trouble getting m core data objects to be deallocated. I even tried the simplest test I could think of and I watched the retain count and it always seems to be higher than I expect. I also put a breakpoint on the dealloc routine for the core data objects and it doesn't seem to get called (at least not unless I specifically add additional releases).

I definitely have [managedObjectContext setRetainsRegisteredObjects:NO] by the way, so that isn't the problem.

Here is an example I've tried that doesn't work:

MobileObject *obj = [NSEntityDescription insertNewObjectForEntityForName:@"MobileObject" inManagedObjectContext:managedObjectContext];

NSLog(@"Object count after creation %d", [obj retainCount]);

NSError *error;
[managedObjectContext save:&error];

NSLog(@"Object count after saving %d", [obj retainCount]);

Each log message prints out "2". Dealloc never gets called. I'd expect the save to cause the object to be released (or autoreleased) since core data should realize it doesn't need to stay around. In that case the retain count of 2 makes sense if there are two autoreleases (one from the creation and one from the save) but that doesn't seem to be the case. If I add

[obj release] 

at the very end of my test, the dealloc routine will get called correctly but I am very confused as to why I need this release at all.

like image 203
Mike Avatar asked Jan 22 '23 17:01

Mike


1 Answers

Saving a CoreData context is not logically related to releasing an NSManagedObject.

In a big program, it is quite common to have the managed object context (moc) all the while your program is running. Objects are added to and removed from the context reflecting the user's action, and the context is also saved once in a while so that the context in memory is synced to what you have on the file. But in this case, saving the context does not mean you're done with the context; you still keep the context and use it just as before the save. So, saving doesn't mean deallocating the objects.

So, if you want to deallocate objects you retain, you need to explicitly release them.

However in this case, insertNewObjectForEntityName:inManagedObjectContext: returns an autoreleased object as written here. So you do not own the object unless you retain it explicitly. If you didn't retain, you shouldn't release it. It's released and dealloc is called automatically when appropriate.

Note that you should never rely on retainCount to see what is going on. For a simplistic object, the number of retainCount would agree with what we expect, but for something complicated like an NSManagedObject, the framework itself needs to keep track of a lot of things, and so might do a lot of retain behind the scenes. For example, even if you do not explicitly retain an object, it might be in a relationship of another object which you own; or CoreData might just decide to keep the object in the memory to cache it.

The only thing to keep in mind is to stick to the standard ownership rule. If you alloc/init or retain, you later release or autorelease it.

Answering your question in the comment, let me state the basic principle here: If an object x needs another object a, x retains a. When x finishes using a, x releases a. Every object x should follow this procedure, whether x is an object which you code, or which Apple's framework provides. If every object follows this principle, there's no leak. So, Apple's code which you don't see follows this. Your code should follow this, too.

This answers your question:

when I "add" a child object to a parent does the parent object automatically retain the object I added?

Yes it does. The parent needs it, so it retains it.

And if I then release the parent object will it release the child or to I have to do that explicitly?

Yes the parent does release the child, because when the parent is dealloced, it finishes using the child, so the child is releaseed.

These points are not usually written in the documentation of the individual methods, because as the rule, every API follows this basic memory management principle, and therefore there's no need to spell them out.

You're encouraged to read Memory Manegement Rules.

like image 152
Yuji Avatar answered Jan 29 '23 11:01

Yuji