iPhone中cocos2d数组中的精灵,内存问题

3

我正在尝试使用数组来跟踪我的精灵,将它们添加和移除到层中,最后清除掉数组中的精灵。

我正在使用以下代码:

Sprite * Trees[50];
Layer * Forest;

Forest =  [Layer node];
Forest.isTouchEnabled = YES;
[self addChild:Forest z:30];

// do this a bunch of times
Trees[0] = [[Sprite spriteWithFile:@"mytree.png"] retain];
[Trees[0] setPosition:cpv(240,160)];
[Forest addChild:Trees[0] z:5];

当我想要销毁一棵树时,我使用:

[Forest removeChild:Trees[0] cleanup:YES];
[Trees[0] release];

我的问题是,当我在Instruments中查看时,我从未回收过那些内存,它们从未降下来。我以为通过释放精灵,它会释放内存。我做错了吗?

3个回答

4
我知道当你在使用cocos2d模拟器时,内存看起来并没有被释放,所以你必须在设备上运行它才能准确地了解情况。关于cocos2d和内存,这里有一个很好的讨论。
我注意到的是,你创建和保留的所有内容都必须被释放,但直到我执行以下操作它才会从内存中释放:
[[TextureMgr sharedTextureMgr] removeAllTextures]; 

我会释放内存。

这是一个更大的例子:

Sprite * sPopup = [[Sprite spriteWithFile:@"popup.png"] retain];
    sPopup.position = cpv(240,440);
    [self addChild: sPopup z:2];
[sPopup release];

然后,在另一个函数中完成sPopup后,我有以下代码:

[[TextureMgr sharedTextureMgr] removeAllTextures]; 

内存得到释放。


3
我的怀疑是你在过度保留。
Trees[0] = [[Sprite spriteWithFile:@"mytree.png"] retain];

如果Trees是函数中的一个局部变量,且spriteWithFile返回了一个具有自动释放的Sprite,则在这种情况下,您不必保留它。
关于延迟释放的部分在苹果文档中讨论了这一点。长话短说,自动释放池的接收者保证对象在其范围内有效。如果你需要超出函数范围的对象(例如Trees是类的属性),那么是的,在这种情况下,你需要一个保留(或者只是合成一个配置为保留的属性)。
通过发出额外的保留,很可能你的保留计数总是太高(永远不会达到0),因此你的对象不会被垃圾回收。
为了安全起见,我建议再审查一下这段谈论对象有效性的内容

我相信你的答案可能是错误的。上面的代码中有两个保留操作,以及两个相应的释放操作。错误不在Patrick的代码中。 - EightyEight
我认为这取决于spriteWithFile方法的工作方式。按照惯例,大多数静态工厂方法都通过autorelease返回(至少所有苹果API都是这样)。如果spriteWithFile在其上调用autorelease返回一个Sprite,则他不需要保留。我相信在他的代码中保留计数始终> 0,这就是为什么内存没有被释放的原因。 - hyuan
保留/释放计数是正确的,但我建议使用NSMutableArray,这样您就不需要额外的保留。 - CodeSmile

0

即使您调用[Trees[x] release],我认为您仍然需要从数组中“删除”该项,例如Trees[x] = nil或其他内容,因为数组本身仍然包含该对象。

在Sprite创建中的'retain'也是不必要的,因为[Forest addChild:z:]也会对其进行保留(据我所知)。


树是一个数组,因此不会保留它存储的对象.. 因此无需从数组中删除它以释放内存。 - EightyEight
是的,这就是为什么在这种情况下我会使用NS(Mutable)Array。 - CodeSmile

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接