cocos2dx3.0 removeFromParent和removeAllChildren含義


顧名思義,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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM