setTouchEnabled prevents destructor from being called

Hello,

I have a class that is a subclass of CCLayer. I found if I call setTouchEnabled(true), the destructor never gets called when my class is removed and cleaned up. If I don’t call setTouchEnabed, the destructor is called properly and everything is cleaned up.

By the way I’m using version 2.0.3 and this behavior occurs on both the simulator and device.

Thank you for any help you can provide.

-Edgar

Designed as this. setTouchEnabled(true) will register this node into CCTouchDispatcher as a standard delegate. CCTouchDispatcher will add this node’s reference count. The same case happens to setKeypadEnabled(bool) and setAccelerometerEnabled(bool).

The best practice is to call setXxxEnabled(false) in MyCustomLayer::onExit()

Thanks for your reply Walzer and for responding so quickly!

I tried your suggestion of calling setTouchEnabled(false) in the onExit() method of my class, but that did not seem to help. When I walked through Cocos2D-X source code, I see that CCLayer::onExit() does remove the delegate. But for some reason my destructor still does not get called.

Here is a simple class I created to demonstrate the issue.

TestLayer::~TestLayer()
{
    // this never gets called
    CCLOG("TestLayer::~TestLayer() called");
}

TestLayer* TestLayer::create()
{
    TestLayer* pRet = new TestLayer();
    if (pRet && pRet->init()) {
        pRet->autorelease();
        return pRet;
    }

    CC_SAFE_DELETE(pRet);
    return NULL;
}

bool TestLayer::init()
{
    if (CCLayer::init()) {
        // if I call setTouchEnabled(true), the destructor does not get called
        // if I remove this call, everything works fine
        this->setTouchEnabled(true);

        return true;
    }

    return false;
}

void TestLayer::onExit()
{
    CCLOG("TestLayer::onExit() called");

    // explicitly calling setTouchEnabled(false) does not help
    // this->setTouchEnabled(false);

    CCLayer::onExit();
}

CCScene* HelloWorld::scene()
{
    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();

    // 'layer' is an autorelease object
    HelloWorld *layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// using the HelloWorld sample
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !CCLayer::init() )
    {
        return false;
    }

    // Init the app.
    AppInfo::sharedAppInfo()->initApp();

    // ask director the window size
    CCSize size = CCDirector::sharedDirector()->getWinSize();

    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.

    // add a "close" icon to exit the progress. it's an autorelease object
    CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                                        "CloseNormal.png",
                                        "CloseSelected.png",
                                        this,
                                        menu_selector(HelloWorld::menuCloseCallback) );
    pCloseItem->setPosition( ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20) );

    // create menu, it's an autorelease object
    CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
    pMenu->setPosition( CCPointZero );
    this->addChild(pMenu, 1);

    /////////////////////////////
    // 3. add your codes below...

    // create a test layer to demonstrate the touch issue
    TestLayer* testLayer = TestLayer::create();
    this->addChild(testLayer);

    return true;
}

void HelloWorld::menuCloseCallback(CCObject* pSender)
{
    // remove all the children to demonstrate the touch issue
    this->removeAllChildrenWithCleanup(true);

    CCDirector::sharedDirector()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}

hi, did you find a solution to this?

I have the same issue, one of my games break after a time when the game is restarted about 5-7 times via replaceScene.
I think this can be the problem of my game too. (I have no idea what can be happenning if this is not the problem)

you shold update cocos2d-x to version 2.0.4. I’m using it ,and it’s OK.no necessary update to 2.1 , I find bugs in 2.1.

You can check the source in 2.0.3 , if you setTouchEnabled(true) in init() method ,it will excute registerWithTouchDispatcher to addStandardDelegate and then onEnter method , it will excute registerWithTouchDispatcher too , so it’s a bug here , but not in 2.0.4.:slight_smile: