UIButton事件函數中刪除自身導致崩潰 和 觸摸事件繼續傳遞

方法2 node->runAction(RemoveSelf::create()); 同時可解決觸摸事件繼續傳遞問題


回調函數裏判斷是彈起事件時會調用UIButton的removeFromParent方法,這時會導致遊戲崩潰,代碼中斷在void Widget::onTouchEnded(Touch *touch, Event *unusedEvent)方法裏的releaseUpEvent()調用處.


1.修改引擎代碼

void Widget::releaseUpEvent()
{
    if (_touchEventListener && _touchEventSelector)
    {
        (_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_ENDED);
    }
    
    if (_touchEventCallback) {
        _touchEventCallback(this, TouchEventType::ENDED);
    }
}

換個位置就好了

調用callback完以後釋放本對象,但代碼沒執行完 繼續調用Listener,這時釋放的地址很可能不爲空,就導致出錯了

2.不需要修改引擎代碼

刪除自身的時候

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

代替原來的removefromparentandcleanup(true);

原理:我們可以看看引擎對removeSelf的實現

不直接調用remove,而是設置一個標誌,在update中檢測到標誌再remove.  

//
// 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;
}


發佈了30 篇原創文章 · 獲贊 2 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章