I can't get removeSelf() to work

Hi Guys,

I’m a total n00b at Corona, and I thought it might be fun to teach myself.  I’ve made lots of progress reading the forums and so on, but I’ve run into a bit of a problem cleaning up objects.

I’ve read several similar threads and I just cannot get my head around what I’m doing wrong - hopefully one of you more experienced people will be able to see it instantly.

When my game levels is over, I have to present a ‘dialogue box’ to my user with some text along the lines of “good work”, or “you failed”, or “time’s up”.  To make it readable, I’ve decided to throw up a background.  When the user acknowledges the dialogue that should go away.

Now, since I’m going to have several dialogues in the software, I thought a standard background would be a good idea to maintain consistency in look and feel.

My code architecture isn’t yet that great - I’m justifying this is my head as “i’m a beginner and this will come in time”

Anyway, let’s get down the code:

local sceneName = "gameCore"    -- exists for printing debug messages local dialogueDG = display.newGroup();  --the display group for the dialog BG local dialogueTxtDG = display.newGroup();  --display group for the text function gc:dialogBG() local fadeInMS = 250;  -- adjust the speed of the dialogue box here, to prevent errors later       --render a dialogue box background     txtBackground = display.newRect(dialogueDG,display.contentCenterX, display.contentCenterY, 100, 100);     txtBackground:setFillColor(1,1,1,0.85);     txtBackground.strokeWidth = 2;     txtBackground:setStrokeColor(0,0,0,1);   --grow the dialogue box background to fill the desired area        transition.scaleBy( txtBackground, {xScale = 4.0, yScale = 1.5, time=fadeInMS});       --I still haven't worked out scaleBy v scaleTo but this "looks" ok on the screen end function gc:dialogBGerase()   local fadeOutMS = 250;  -- adjust the speed of the shrink here, to save errors later      --shrink the dialogue background   transition.scaleTo( txtBackground, {xScale = 0.25, yScale = 0.67, time=fadeOutMS});         --define the erase method used in the timer below      local function eraseDialogBG()     display.remove(txtBackground);          if txtBackground ~=nil then        txtBackground:removeSelf();         -- line 134 in my lua code     end         end      timer.performWithDelay(fadeOutMS, eraseDialogBG, 0);    end  

and here is the result in the Output:

2014-04-26 23:26:11.506 Corona Simulator[10422:507] Runtime error

/Users/username/code/moocow/octopus/gameCore.lua:134: attempt to call method ‘removeSelf’ (a nil value)

stack traceback:

    /Users/username/code/moocow/octopus/gameCore.lua:134: in function ‘_listener’

    ?: in function <?:141>

    ?: in function <?:218>

Program stopped (pid: 10422).

Program completed in 11.41 seconds (pid: 10422).

because I’m still writing stuff, I’m just using stub code in places - this is the function that calls the cleanup - it appears to be working correctly.

function gc.levelEnd() gc.dialogBG(); timer.performWithDelay(2000, gc.dialogBGerase, 0); end

I simply cannot see where I’m going wrong - any help you could offer would be appreciated. 

Possible daft answer: removeSelf removes it from a group (it is the same as  and you haven’t put it in one (might have removed this code, I know :))

You know txtBackground is not nil, otherwise line 134 wouldn’t be executed. So it can’t be that, it has to be a consequence of that. Could it be an internal reference to the owning group (it must know its group otherwise it couldn’t remove itself from the group) is returning nil (because it’s not in the group) and it is then trying to call some internal function with nil which should be a reference to the owning group ?

If not this, has txtBackground been corrupted - could you print out its table so that at least you know it is actually a displayObject ?

ok - well I gave it a go (I think I screwed it up somehow)…

I commented out txtBackground:removeSelf(); and replaced it with print(txtBackground);

I got this:

2014-04-27 00:34:32.994 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.026 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.059 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.092 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.158 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.191 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.257 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.290 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.323 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.356 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.422 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.455 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.521 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.554 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.586 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.620 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.686 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.719 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.784 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.818 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.851 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.884 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.949 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.982 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.049 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.081 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.115 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.148 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.215 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.247 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.313 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.346 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.379 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.412 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.478 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.511 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.544 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.577 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.610 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.642 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.676 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.742 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.775 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.808 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.840 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.874 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.907 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.940 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:35.006 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:35.039 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:35.072 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:35.105 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:35.137 Corona Simulator[10842:507] table: 0x7fd1f9db9250

Until I stopped the simulator - and it was accelerating (or at least it seemed to be).

This suggests to me that the print code I gave it has returned an index, and somewhere along the way a timer has got into a loop?

Well my loop hypothesis would appear to be wrong -

I changed the code to:

function gc:dialogBGerase() &nbsp;--erases dialogue backgrounds &nbsp; local fadeOutMS = 250; &nbsp;&nbsp; &nbsp; --shrink the dialogue background &nbsp; transition.scaleTo( txtBackground, {xScale = 0.25, yScale = 0.67, time=fadeOutMS}); &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; --define the erase method used in the timer below &nbsp;&nbsp; &nbsp; &nbsp;local function eraseDialogBG() &nbsp; &nbsp; display.remove(txtBackground); &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; if txtBackground ~=nil then &nbsp; &nbsp; &nbsp; print(txtBackground); &nbsp; &nbsp; &nbsp; txtBackground:removeSelf(); &nbsp; &nbsp; &nbsp; timer.cancel(fadeOutTimer); &nbsp; &nbsp; end &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp;&nbsp; &nbsp; fadeOutTimer = timer.performWithDelay(fadeOutMS, eraseDialogBG, 0); &nbsp;&nbsp; &nbsp;&nbsp; end &nbsp;

And got:

2014-04-27 00:39:34.095 Corona Simulator[10872:507] table: 0x7fa40a5f02d0

2014-04-27 00:39:36.108 Corona Simulator[10872:507] table: 0x7fa40a5f02d0

2014-04-27 00:39:36.109 Corona Simulator[10872:507] Runtime error

/Users/username/code/moocow/octopus/gameCore.lua:137: attempt to call method ‘removeSelf’ (a nil value)

stack traceback:

    /Users/username/code/moocow/octopus/gameCore.lua:137: in function ‘_listener’

    ?: in function <?:141>

    ?: in function <?:218>

2014-04-27 00:39:36.405 Corona Simulator[10872:507] table: 0x7fa40a5f02d0

2014-04-27 00:39:36.406 Corona Simulator[10872:507] Runtime error

I’ve added loop protection to the function - just in case 
 

function gc:dialogBGerase() &nbsp;--erases dialogue backgrounds &nbsp; local fadeOutMS = 250; &nbsp; local loopProtection = false &nbsp;&nbsp; &nbsp; --shrink the dialogue background &nbsp; transition.scaleTo( txtBackground, {xScale = 0.25, yScale = 0.67, time=fadeOutMS}); &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; --define the erase method used in the timer below &nbsp;&nbsp; &nbsp; &nbsp;local function eraseDialogBG() &nbsp; &nbsp; display.remove(txtBackground); &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; if txtBackground ~=nil then &nbsp; &nbsp; &nbsp; print(txtBackground); &nbsp; &nbsp; &nbsp; print(txtBackground.parent); &nbsp; &nbsp; &nbsp; txtBackground:removeSelf(); &nbsp; &nbsp; &nbsp; timer.cancel(fadeOutTimer); &nbsp; &nbsp; &nbsp; txtBackground = nil; &nbsp; &nbsp; end &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp;&nbsp; &nbsp; if loopProtection == false then &nbsp; fadeOutTimer = timer.performWithDelay(fadeOutMS, eraseDialogBG,0); &nbsp; loopProtection = true; &nbsp; end; &nbsp;&nbsp; end &nbsp;

And now it’s erroring in the same way - but at least it isn’t looping that error.

I think I found my problem - 

This function is called by:

function gc.levelEnd() &nbsp; gc.dialogBG(); &nbsp; timerEraseDialog = timer.performWithDelay(2000, gc.dialogBGerase, 0); end &nbsp;

Because of ‘0’ it will loop forever.  I’ve changed the code to 

function gc.levelEnd() &nbsp; gc.dialogBG(); &nbsp; timerEraseDialog = timer.performWithDelay(2000, gc.dialogBGerase, 1); end &nbsp;

And from what I can tell, it works properly now.

Explanation - first time around it goes off to shrink the rectangle, then it removes the rectangle, then it nils the rectangle out and ‘removes self’, because that timer was set to loop infinitely with no ‘cancel timer’ anywhere, it kept attempting to perform those tasks on a non-existent rectangle.  The only question left - why is the there a table index when I’ve nil’d it out - surely it should garbage collect?

Possible daft answer: removeSelf removes it from a group (it is the same as  and you haven’t put it in one (might have removed this code, I know :))

You know txtBackground is not nil, otherwise line 134 wouldn’t be executed. So it can’t be that, it has to be a consequence of that. Could it be an internal reference to the owning group (it must know its group otherwise it couldn’t remove itself from the group) is returning nil (because it’s not in the group) and it is then trying to call some internal function with nil which should be a reference to the owning group ?

If not this, has txtBackground been corrupted - could you print out its table so that at least you know it is actually a displayObject ?

ok - well I gave it a go (I think I screwed it up somehow)…

I commented out txtBackground:removeSelf(); and replaced it with print(txtBackground);

I got this:

2014-04-27 00:34:32.994 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.026 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.059 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.092 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.158 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.191 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.257 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.290 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.323 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.356 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.422 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.455 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.521 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.554 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.586 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.620 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.686 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.719 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.784 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.818 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.851 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.884 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.949 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:33.982 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.049 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.081 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.115 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.148 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.215 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.247 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.313 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.346 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.379 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.412 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.478 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.511 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.544 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.577 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.610 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.642 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.676 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.742 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.775 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.808 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.840 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.874 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.907 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:34.940 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:35.006 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:35.039 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:35.072 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:35.105 Corona Simulator[10842:507] table: 0x7fd1f9db9250

2014-04-27 00:34:35.137 Corona Simulator[10842:507] table: 0x7fd1f9db9250

Until I stopped the simulator - and it was accelerating (or at least it seemed to be).

This suggests to me that the print code I gave it has returned an index, and somewhere along the way a timer has got into a loop?

Well my loop hypothesis would appear to be wrong -

I changed the code to:

function gc:dialogBGerase() &nbsp;--erases dialogue backgrounds &nbsp; local fadeOutMS = 250; &nbsp;&nbsp; &nbsp; --shrink the dialogue background &nbsp; transition.scaleTo( txtBackground, {xScale = 0.25, yScale = 0.67, time=fadeOutMS}); &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; --define the erase method used in the timer below &nbsp;&nbsp; &nbsp; &nbsp;local function eraseDialogBG() &nbsp; &nbsp; display.remove(txtBackground); &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; if txtBackground ~=nil then &nbsp; &nbsp; &nbsp; print(txtBackground); &nbsp; &nbsp; &nbsp; txtBackground:removeSelf(); &nbsp; &nbsp; &nbsp; timer.cancel(fadeOutTimer); &nbsp; &nbsp; end &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp;&nbsp; &nbsp; fadeOutTimer = timer.performWithDelay(fadeOutMS, eraseDialogBG, 0); &nbsp;&nbsp; &nbsp;&nbsp; end &nbsp;

And got:

2014-04-27 00:39:34.095 Corona Simulator[10872:507] table: 0x7fa40a5f02d0

2014-04-27 00:39:36.108 Corona Simulator[10872:507] table: 0x7fa40a5f02d0

2014-04-27 00:39:36.109 Corona Simulator[10872:507] Runtime error

/Users/username/code/moocow/octopus/gameCore.lua:137: attempt to call method ‘removeSelf’ (a nil value)

stack traceback:

    /Users/username/code/moocow/octopus/gameCore.lua:137: in function ‘_listener’

    ?: in function <?:141>

    ?: in function <?:218>

2014-04-27 00:39:36.405 Corona Simulator[10872:507] table: 0x7fa40a5f02d0

2014-04-27 00:39:36.406 Corona Simulator[10872:507] Runtime error

I’ve added loop protection to the function - just in case 
 

function gc:dialogBGerase() &nbsp;--erases dialogue backgrounds &nbsp; local fadeOutMS = 250; &nbsp; local loopProtection = false &nbsp;&nbsp; &nbsp; --shrink the dialogue background &nbsp; transition.scaleTo( txtBackground, {xScale = 0.25, yScale = 0.67, time=fadeOutMS}); &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; --define the erase method used in the timer below &nbsp;&nbsp; &nbsp; &nbsp;local function eraseDialogBG() &nbsp; &nbsp; display.remove(txtBackground); &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; if txtBackground ~=nil then &nbsp; &nbsp; &nbsp; print(txtBackground); &nbsp; &nbsp; &nbsp; print(txtBackground.parent); &nbsp; &nbsp; &nbsp; txtBackground:removeSelf(); &nbsp; &nbsp; &nbsp; timer.cancel(fadeOutTimer); &nbsp; &nbsp; &nbsp; txtBackground = nil; &nbsp; &nbsp; end &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp;&nbsp; &nbsp; if loopProtection == false then &nbsp; fadeOutTimer = timer.performWithDelay(fadeOutMS, eraseDialogBG,0); &nbsp; loopProtection = true; &nbsp; end; &nbsp;&nbsp; end &nbsp;

And now it’s erroring in the same way - but at least it isn’t looping that error.

I think I found my problem - 

This function is called by:

function gc.levelEnd() &nbsp; gc.dialogBG(); &nbsp; timerEraseDialog = timer.performWithDelay(2000, gc.dialogBGerase, 0); end &nbsp;

Because of ‘0’ it will loop forever.  I’ve changed the code to 

function gc.levelEnd() &nbsp; gc.dialogBG(); &nbsp; timerEraseDialog = timer.performWithDelay(2000, gc.dialogBGerase, 1); end &nbsp;

And from what I can tell, it works properly now.

Explanation - first time around it goes off to shrink the rectangle, then it removes the rectangle, then it nils the rectangle out and ‘removes self’, because that timer was set to loop infinitely with no ‘cancel timer’ anywhere, it kept attempting to perform those tasks on a non-existent rectangle.  The only question left - why is the there a table index when I’ve nil’d it out - surely it should garbage collect?