您的位置:首页 > 移动开发 > Cocos引擎

cocos2dx3.0 removeFromParent和removeAllChildren含义

2016-04-18 13:55 495 查看
顾名思义,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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: