顧名思義,removeFromParent就是把自己從父親那里移除,removeAllChildren就是移除自己所有的孩子,這些方法的具體實現都在基類Node里面,通過查看代碼也很容易看到怎么實現的。
現在主要看下他們兩個的調用順序
示例代碼如下:
比如自定義一個類Layer,
#ifndef _MAINMENU_H1_
#define _MAINMENU_H1_ #include "cocos2d.h" using namespace cocos2d; using namespace std; class Layer1 : public Layer { public: Layer1(); virtual ~Layer1(); bool init(); virtual bool onTouchBegan(Touch *pTouch, Event *pEvent); virtual void onTouchMoved(Touch *pTouch, Event *pEvent); virtual void onTouchEnded(Touch *pTouch, Event *pEvent); virtual void onTouchCancelled(Touch *pTouch, Event *pEvent); string haha; CREATE_FUNC(Layer1); }; #endif
#include "Layer1.h"
Layer1::Layer1()
{
}
Layer1::~Layer1() { printf("析構函數"); } bool Layer1::init() { // this->setTouchEnabled(true); auto listen = EventListenerTouchOneByOne::create(); listen->onTouchBegan = CC_CALLBACK_2(Layer1::onTouchBegan, this); listen->onTouchMoved = CC_CALLBACK_2(Layer1::onTouchMoved, this); listen->onTouchEnded = CC_CALLBACK_2(Layer1::onTouchEnded, this); listen->onTouchCancelled = CC_CALLBACK_2(Layer1::onTouchCancelled, this); // listen->setSwallowTouches(true); Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listen, this); return true; } bool Layer1::onTouchBegan(Touch *touch, Event * pEvent) { printf("Layer1 began\n"); this->removeFromParent(); this->removeAllChildren(); // for(int i=0;i<100000;i++){ // printf("char=%s",haha.c_str()); // } return true; } void Layer1::onTouchEnded(Touch *touch, Event * pEvent) { printf("Layer1 end\n"); } void Layer1::onTouchCancelled(Touch *touch, Event *pEvent) { printf("Layer1 cancel\n"); } void Layer1::onTouchMoved(Touch *touch, Event *pEvent) { printf("Layer1 Move\n"); }
AppDelegate
auto scene = Scene::create(); auto layer1=Layer1::create(); scene->addChild(layer1); director->runWithScene(scene);
當點擊界面的時候,會報錯,看標紅的地方,很容易理解什么原因 removeFromParent之后,Layer1實例已經釋放了,在調用就會報錯(但是在cocos2d-iphone中,他們的順序是無關緊要的,都可以正確運行,通過調試得知,當調用RemoveFromPanrent的時候,dealloac沒有馬上調用,而c++中的析構函數會立即調用,我猜想原因可能就在這里吧),然后把順序反過來,果然正確執行.
下面再看下一個問題,移除Layer1實例的時候,能否只調用removeFromParent,而不調用removeAllChildren().這個可以通過析構函數來判斷,新建一個Layer2的類
#ifndef _MAINMENU_H222_
#define _MAINMENU_H222_ #include "cocos2d.h" using namespace cocos2d; class Layer2 : public Layer { public: Layer2(); virtual ~Layer2(); bool init(); virtual bool onTouchBegan(Touch *pTouch, Event *pEvent); virtual void onTouchMoved(Touch *pTouch, Event *pEvent); virtual void onTouchEnded(Touch *pTouch, Event *pEvent); virtual void onTouchCancelled(Touch *pTouch, Event *pEvent); CREATE_FUNC(Layer2); }; #endif
#include "Layer2.h"
Layer2::Layer2()
{
}
Layer2::~Layer2(){ printf("Layer2析構函數"); } bool Layer2::init() { //this->setTouchEnabled(true); auto listen = EventListenerTouchOneByOne::create(); listen->onTouchBegan = CC_CALLBACK_2(Layer2::onTouchBegan, this); listen->onTouchMoved = CC_CALLBACK_2(Layer2::onTouchMoved, this); listen->onTouchEnded = CC_CALLBACK_2(Layer2::onTouchEnded, this); listen->onTouchCancelled = CC_CALLBACK_2(Layer2::onTouchCancelled, this); // listen->setSwallowTouches(true); Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listen, this); return true; } bool Layer2::onTouchBegan(Touch *touch, Event * pEvent) { printf("Layer2 began\n"); return true; } void Layer2::onTouchEnded(Touch *touch, Event * pEvent) { printf("Layer2 end\n"); // pEvent->stopPropagation(); } void Layer2::onTouchCancelled(Touch *touch, Event *pEvent) { printf("Layer2 cancel\n"); } void Layer2::onTouchMoved(Touch *touch, Event *pEvent) { printf("Layer2 Move\n"); pEvent->stopPropagation(); }
Layer1修改,去掉
this->removeAllChildren();這一行代碼
Appdelegate
auto scene = Scene::create();
// scene->addChild(MainMenu::create());
auto layer1=Layer1::create(); //int fff=layer1->getReferenceCount(); auto layer2=Layer2::create(); layer1->addChild(layer2); scene->addChild(layer1); // layer2->retain(); // run director->runWithScene(scene);
通過運行發現,Layer2會執行析構函數,那么Layer2是在什么位置被刪除的呢,通過看removeFromParent的源碼發現,並沒有發現刪除Layer2的代碼,
而在removeAllChildren()中很容易發現是
_children.clear();但是removeFromParent中並沒有這個代碼,最后通過分析找到了地方,原來Layer的基類Node有一個_children的Vector數組,當
Node釋放的時候,他的屬性_children也會釋放,然后這個屬性會調用析構函數,在析構函數里面調用了clear()方法,如下代碼
/** Destructor */
~Vector<T>()
{
CCLOGINFO("In the destructor of Vector.");
clear();
},
,從而使Layer1的孩子Layer2也釋放。
所以分析得知,要移除某個cocos2d類的實例,在保證沒有內存泄露的情況下(內存泄露的話,兩個方法都調也不行),調用 removeFromParent就可刪除自身,無需調用removeAllChildren(),如果兩個類都想調用,那么先調用removeAllChildren,在調用removeFromParent。