Switching Scenes causes EXC_BAD_ACCESS on touch events

So i have a main menu scene that has a menu item that launches an in game scene:

auto scene = MeadowScene::createScene();
Director::getInstance()->replaceScene(TransitionFade::create(1, scene));

the MainScene is started in AppDelegate.cpp like this:

auto scene = MainScene::createScene();
Director::getInstance()->runWithScene(scene);

I have several event listeners for many interactive sprites on the MeadowScene. The Event listener looks something like this:

bool Snail::addTouchEvent() {
    auto listener = EventListenerTouchOneByOne::create();
    listener->setSwallowTouches(false);
    
    listener->onTouchBegan = [&] (Touch* touch, Event* event){
        listener->setSwallowTouches(true);
        // get the sprite from the event object
        auto sprite = event->getCurrentTarget();
        
        Vec2 pt = touch->getLocation();
        auto recTemp = sprite->getBoundingBox();
        
        if (recTemp.containsPoint(sprite->getParent()->convertToNodeSpace(pt) )) {
            Director::getInstance()->getEventDispatcher()->pauseEventListenersForTarget(sprite);
            this->animate(sprite);
            
        }
        return true;
    };
    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this->sprite);
    return true;
    
}

When the MeadowScene is the first scene to load then everything works fine however when the MainScene replaces itself with MeadowScene then I start having issues. When the different interactive elements get touched I get this error:

Thread 1: EXC_BAD_ACCESS (code=1, address=0x178)

That happens in this function:

void EventListenerTouchOneByOne::setSwallowTouches(bool needSwallow)
{
    _needSwallow = needSwallow; // Thread 1: EXC_BAD_ACCESS (code=1, address=0x178)
}

Any idea why this might be happening? is there a step that I am missing in switching scenes?

You are always returning true?

I’d return true in the if block and return false otherwise.

I gave that a shot and that’s probably how I should do it but it was still giving me an error. I found the issue though:

listener->setSwallowTouches(false);

listener->onTouchBegan = [&] (Touch* touch, Event* event){
    listener->setSwallowTouches(true);

Removing the second call the setSwallowTouches worked.

Yup, do you know why?

1 Like

Is there a way to swallow the touch and prevent other event listeners from getting the event only if the element the event listener is for has been touched? i have an event listener per element. Or is the only way to do that to have a single global listener that handles it all for everything?

Per element works just fine.

No sir, I do not.

First, this should be true.

Second you were experiencing a scope issue. You were calling listener inside a lambda of the same listener.

That makes sense. Thank you for your help and very quick responses. What an awesome community

Ask anything you need to. This is how we all grow as developers.

1 Like