我的游戏使用到了cocos2d 框架,游戏结构比较简单,一个 MenuScene, 一个 GameScene
GameScene继承自 CCLayer
由于要使用一个比较大的地形(总之比iTouch4g的屏幕要大)
因此我选择使用可以移动的场景用来实现这个功能
之前我的GameScene就是仅有的一个 CCLayer 对象~
但是如果要实现场景的移动的话,则必须要在这个CCLayer里面在添加一个 子 CCLayer 对象
将位置不用改变的小地图,joyStick,游戏暂停重来等按钮放在母层里面,
这样游戏场景在被移动的时候,这些位置不用改变的元素就不会随着游戏场景腾挪
然而,就在这个时候,问题出现了~
这个问题我也是偶然才发现的,之前游戏的持久性我都有过测试,“重来”一百次也不会有什么问题
说明在GameScene dealloc的时候将该干掉的都给干掉了,
但是在我增加子层了之后,我发现对于比较复杂的地图,重来不了两下游戏就会crash掉
查看控制台,发现爆出的错误就是 “Received Memery Warning”
除此之外,再没有其他的提示~
于是我求助Google大神,但是收效甚微
我一遍又一遍的重来,试图能够发现导致游戏崩溃的根本原因
在xcode4。2里面,我发现已经找不到Instruments的身影了
这也是在可以理解的范围,毕竟XCode从3个多G降到1个多G,不能不说被阉割掉了很多东西
我发现了一个比较有意思的功能,Analyze,快捷键是 Command + shift + b
Command +b是生成的快捷键,这是一个很常用的快捷键,对我来说仅次于 Command +r(编译并且在完成之后运行)了~
这个Analyze相当于对源代码进行处理,将有可能导致内存泄露的地方给报告出来~
不能说这个功能很鸡肋,因为我确实靠这个功能找到了几处没有delete的对内存分配
但是,也是仅此而已,我并没有靠着这个功能找到 Received Memery Warnning的原因~
如果用Cocos2d用的比较多的肯定都知道,凡继承自CCNode的类型在一定程度上如果作为Scene场景的成员节点
都是不用在Scene的 dealloc方法中自主去释放掉的,cocos2d会“很智能”的将这些子节点给清理掉~
离我的问题很近了!!就是因为cocos2d有点儿智能但是又不是智能到完美无缺,因此才导致了我所遇到的问题!!
这个也是我整了一个下午灵光一闪间突然想到的,我就像,母层的dealloc虽然是能将其下的所有子节点给清理掉了
但是,子层里面如果也是以容器的身份出现,里面也盛放了很多孙子节点,那么祖母节点不一定能将这些孙子辈们给干掉~
事实证明我的猜测不错,我先后试过这么一些方法:
1。将子层由CCLayer改成CCNode;(不管用,重来不到10次依然会内存耗尽崩溃)
2。在母层的dealloc方法中主动去调用子层的dealloc方法(重来的第一次就会报错,很明显,子层将会被dealloc两次,肯定会造成类似内存访问出错的错误)
3。我在母层的dealloc方法中,在 【super dealloc】之前添加子层 removeAllChildrenWithCleanup:YES的代码
在第3种方法的实验过程中,我得到了满意的结果,即使重来100次,Received Memery Warning 的错误也不会再报出了~
那么,更加证明了我的推测:
Scene 的 dealloc 仅能智能地将所有的子辈节点给 dealloc 掉,
如果子辈中有充当容器身份的 CCLayer,是不能将其所包含的孙子辈继承自 CCNode 的对象智能清理掉的!!
用一句形象的话语来概括:山高皇帝远 ^ ^
PS:其实以前如果在Scene中添加其他类似容器这样的CCLayer的时候,都会新建一个类
在这个新建出来的类的dealloc方法中做好所有的清理工作
这样倒是不会有什么问题了,因为所谓的智能清理也不过就是调用所有子辈节点的dealloc方法
换句话说,如果子辈的dealloc方法没有给子辈自己擦好屁股以至于发生了内存泄露,母亲大人也是毫无办法的~