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

关于cocos2dx widget窗口中的关闭按钮 删除自身 的时候崩溃bug

2015-04-07 20:35 267 查看
回调函数里判断是弹起事件时会调用UIButton的removeFromParent方法,这时会导致游戏崩溃,代码中断在void
Widget::onTouchEnded(Touch *touch, Event *unusedEvent)方法里的releaseUpEvent()调用处。

响应UIButton的触摸弹起事件时,删除UIButton控件崩溃

修改代码解决方法1

[plain]
view plaincopy





解决办法
void Widget::releaseUpEvent()
{
if (_touchEventListener && _touchEventSelector)
{
(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_ENDED);
}

if (_touchEventCallback) {
_touchEventCallback(this, TouchEventType::ENDED);
}
}
换个位置就好了
调用callback完以后释放本对象,但代码没执行完 继续调用Listener,这时释放的地址很可能不为空,就导致出错了。

2.不需要修改引擎代码

释放的时候改用

改用
widget->runAction(RemoveSelf::create());

代替原来的removeFromParent()

原理:我们可以看看引擎对removeSelf的实现

[cpp]
view plaincopy





//
// Remove Self
//
RemoveSelf * RemoveSelf::create(bool isNeedCleanUp /*= true*/)
{
RemoveSelf *ret = new RemoveSelf();

if (ret && ret->init(isNeedCleanUp)) {
ret->autorelease();
}

return ret;
}

bool RemoveSelf::init(bool isNeedCleanUp) {
_isNeedCleanUp = isNeedCleanUp;
return true;
}

void RemoveSelf::update(float time) {
CC_UNUSED_PARAM(time);
_target->removeFromParentAndCleanup(_isNeedCleanUp);
}

RemoveSelf *RemoveSelf::reverse() const
{
return RemoveSelf::create(_isNeedCleanUp);
}

RemoveSelf * RemoveSelf::clone() const
{
// no copy constructor
auto a = new RemoveSelf();
a->init(_isNeedCleanUp);
a->autorelease();
return a;
}

弹起事件中不是直接调用remove,而是设置一个标志,在update中检测到标志再remove.

3.修改源码

void Widget::pushDownEvent()

{

+ this->retain();

if (_touchEventCallback) {

_touchEventCallback(this, TouchEventType::BEGAN);

}

void Widget::pushDownEvent()

{

(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_BEGAN);

}

+ this->release();

}

void Widget::moveEvent()

{

+ this->retain();

if (_touchEventCallback) {

_touchEventCallback(this, TouchEventType::MOVED);

}

void Widget::moveEvent()

{

(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_MOVED);

}

+ this->release();

}

void Widget::releaseUpEvent()

{

-

+ this->retain();

if (_touchEventCallback) {

_touchEventCallback(this, TouchEventType::ENDED);

}

void Widget::releaseUpEvent()

{

(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_ENDED);

}

+ this->release();

}

void Widget::cancelUpEvent()

{

+ this->retain();

if (_touchEventCallback)

{

_touchEventCallback(this, TouchEventType::CANCELED);

void Widget::cancelUpEvent()

{

(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_CANCELED);

}

-

+ this->release();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: