在Objective C中,为什么我的核心数据对象不会被释放?

问题描述:

我有很多麻烦使m个核心数据对象被释放。我甚至尝试了最简单的测试,我可以想到,我看着保留计数,它总是似乎高于我的期望。我也为核心数据对象的dealloc例程放了一个断点,它似乎没有被调用(至少没有,除非我特别添加额外的版本)。

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).

我确实有[managedObjectContext setRetainsRegisteredObjects:NO]顺便说一句,所以这不是问题。

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]);

每个日志消息都打印出2。 Dealloc从不被调用。我希望保存导致对象被释放(或自动释放),因为核心数据应该意识到它不需要留下来。在这种情况下,保留计数2是有意义的,如果有两个自动释放(一个来自创建和一个来自保存),但似乎不是这样。如果我添加

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] 

在我的测试的最后,dealloc例程将被正确调用,但我很困惑,为什么我需要这个版本。

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.

保存CoreData上下文不是与发布 NSManagedObject

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

在一个大程序中,在程序运行时,管理对象上下文(moc)是很常见的。对象被添加到反映用户动作的上下文中并从中移除,并且上下文也会在一段时间内保存一次,以便内存中的上下文与您在文件上拥有的内容同步。但在这种情况下,保存上下文并不意味着您已完成上下文;你仍然保留上下文并使用它就像保存之前一样。所以,保存并不意味着释放对象。

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.

这种情况下, insertNewObjectForEntityName:inManagedObjectContext:会将自动释放的对象返回为此处。所以你不拥有对象,除非你明确保留它。如果你没有保留,你不应该释放它。它被释放,并在适当时自动调用 dealloc

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.

注意,你不应该依赖 retainCount 查看发生了什么。对于一个简单的对象, retainCount 的数量将与我们期望的一致,但对于像 NSManagedObject 框架本身需要跟踪很多事情,因此可能会在后台做很多 retain 。例如,即使你没有显式地保留一个对象,它可能在你拥有的另一个对象的关系中;或者CoreData可能只是决定将对象保存在内存中以进行缓存。

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.

唯一要记住的是坚持标准所有权规则。如果 alloc / init retain ,您以后 release autorelease

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.

在注释中回答你的问题,让我在这里说明一下基本原则:
如果一个对象 x 需要另一个对象 a x retain s a 。当 x 完成使用 a x release s a 。每个对象 x 应遵循此过程,不管 x 是您编码的对象还是Apple的框架提供的。如果每个对象遵循这个原则,没有泄漏。所以,你没有看到的苹果的代码遵循这一点。

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.

这会回答您的问题:


当我添加子对象到父对象时,父对象是否自动保留我添加的对象?

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?

是父级释放子级,因为当父级 dealloc ed,它完成使用孩子,所以孩子是 release ed。

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

这些点通常不是写在各个方法的文档中,因为作为规则,每个API都遵循这种基本的内存管理原则,因此不需要拼写

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.

建议您阅读内存管理规则