问题描述
我有一个GameScene类是不一个单例实例。因此,每当用户选择一个新级别并将静态/共享数据保存在不同的单例类(例如GameManager)中时,我就分配和释放它。
我使用 ARC 。我想了解如果我的方法是正确的内存管理的观点。换句话说,在清理时调用removeUnusedSpriteFrames就够了吗?这会删除所有的精灵在game-art-forLevelOne-hd.plist?我应该用CCSpriteBatchNode做一些事吗?
- (void)loadGameArtFileForLevelOne //我在交换机中这样做,简化阅读
{
CCSpriteFrameCache * frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:@game-art-forLevelOne-hd.plist];
CCSpriteBatchNode * sharedSpriteBatchNode = [CCSpriteBatchNode batchNodeWithFile:@game-art-forLevelOne-hd.png];
}
//由于dealloc对于ARC代码不推荐使用,我更喜欢在清理时删除未使用的sprite和纹理
- (void)cleanup
{
[[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
}
我在CCSpriteBatch节点的dealloc方法中添加了一个CCLOG调用。当我加载GameScene,然后回到菜单我看到删除未使用的纹理的日志,如预期,但我没有看到CCSpriteFrameCache的dealloc方法的任何日志。 * !警告:请参阅下面的编辑 - 我的错误! *
编辑:对不起,我的意思是我没有看到dealloc方法的任何日志of CCSpriteBatch
这和我想免费有关,并删除所有与Sprite相关的内存。
一旦我明白了这一点,我将优化这一点(例如有一个精灵表为每个级别 - 例如世界1和一个精灵表为每个背景)。
有任何建议吗?
>
我假设你在某处添加了 CCSpriteBatchNode
节点,虽然你发布的代码没有显示它发生在一个开关,所以我认为在一个完全不同的设置)。
在这里,也许需要澄清一下。
CCSpriteFrameCache
是一个缓存:一个存储,其中所有的精灵获得,以便随时可以重复使用。
CCSpriteBatchNode
是一种用于提高Open GL层性能的机制,原则上与缓存无关。
我理解,如果你有一些sprite通过批处理节点仍然存在于一些层/节点/场景中,那么它不会被认为是未使用,并且不会被你的清除码。实际上,它正在使用中。
对于您的问题:
好吧,我认为这取决于你的应用程序什么可以被认为是良好的清理。从缓存中删除未使用的精灵当然是肯定的;但你也可以做其他事情:卸载您加载的音频资源;删除未使用的场景部分(如果需要,可以重新加载);
希望这有帮助。
CCSpriteFrameCache
是单例,所以它应该存在于程序的生命周期但我打赌是这种情况):
CCSpriteFrameCache * frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
所以,我不会担心Cache不会被删除;重要的是其内容被清空。
I got a GameScene class that is not a singleton instance. Hence I allocate and deallocate it every time the user chooses a new level and keep the "static"/"shared" data in a different singleton class (E.g. GameManager).
I am using ARC. I would like to understand if my approach is correct under the memory management point of view. In other words, is it enough to call "removeUnusedSpriteFrames" at cleanup? Will this remove all sprites in game-art-forLevelOne-hd.plist? Should I do something also with the CCSpriteBatchNode?
-(void) loadGameArtFileForLevelOne //I do this in a switch but this is to simplify the reading
{
CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:@"game-art-forLevelOne-hd.plist"];
CCSpriteBatchNode * sharedSpriteBatchNode = [CCSpriteBatchNode batchNodeWithFile:@"game-art-forLevelOne-hd.png"];
}
//As dealloc is deprecated for ARC code, I prefer to remove unused sprites and texture on cleanup
-(void) cleanup
{
[[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
}
I added a CCLOG call in the dealloc method of CCSpriteBatch node. When I load the GameScene and then go back to the menu I see the log of "remove unused texture" as expected but I don't see any log of the dealloc method of CCSpriteFrameCache. *!! Warning: See edit below - my mistake!!*
EDIT: Sorry, I meant I don't see any log of the dealloc method of CCSpriteBatch
This concerns me slightly as I want to "free" and remove all memory related to the Sprites for the level.
Once I understood this I will then "optimize" this bit (e.g. have one sprite sheet for each class of level - e.g. world 1 - and one sprite sheet for each background).
Any suggestion?
EDIT:
I assume you are adding the CCSpriteBatchNode
node somewhere, although the code you posted does not show it (you also mention, it happens in a switch, so I think in a completely different settings). If so, it will not be deallocated until you remove it from where you added it to.
Here, maybe, a clarification is in order.
The CCSpriteFrameCache
is a cache: a piece of storage where all the sprites get in order to be readily available for reuse.
The CCSpriteBatchNode
is a mechanism for improving performance in the Open GL layer in principle totally unrelated from the cache.
I understand that if you have some sprite used through a batch node still present in some layer/node/scene, than it will not be considered "unused" and will not be removed by your cleanup code. Actually, it is in use. The cached sprite will become "unused" when you remove it from all the nodes that refers to it.
As to your question:
Well, I think that it depends on your app what could be considered good cleanup. Removing unused sprites from the cache is certainly ok; but you might also do other things: unloading audio resources you loaded; removing parts of the scene that are not used (and could be reloaded if required); etc.
Hope this helps.
CCSpriteFrameCache
is a singleton, so it shall exist for the lifetime of the program (it could be different, but I bet this is the case):
CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
So, I would not be worried at the fact that the Cache is not deleted; what matters is that its content is emptied.
这篇关于Cocos2d,iOS:从缓存中删除sprite的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!