why do corona sdk's scene hide event not fired? and why timers are still printing stuff into the console even though i remove the scene?

Hello

 

this is how I start the timers

local composer = require( "composer" ) local scene = composer.newScene() timersArray = {} function scene:create( event ) function performTimedEvents(timeString) local function onTimer( event ) local params = event.source.params if(arg == 5) then timer.cancel( event.source ) return end end for i=1,10 do --print("performWithDelay "..sliceStars(timeString)[i]) timersArray[i] = timer.performWithDelay( 1000\*sliceStars(timeString)[i], onTimer ) timersArray[i].params = { n = i } end end performTimedEvents(pagesTimers[currentPage]) end

this is how I cancel the timers (before leaving the scene) but they are still there when I leave the scene, the timers are still printing stuff into the console… notice this specific line timer.cancel(timersArray[j])

 

function flushTimers() pageSequence(5) print("QQQtimersArray") print\_r(timersArray) for j=1,#timersArray do print("didCancelTimer "..j) timer.cancel(timersArray[j]) --timer.pause(timersArray[j]) timersArray[j] = nil end timersArray = {} print\_r(timersArray) print("didReturn"); end

also why scene:hide is not being fired, it used to work at old times when we had storyboard with exit, but this hide callback is not getting called, please help :frowning:
 

function scene:hide( event ) print("YYY\_hide\_!!!") local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then print("YYY\_hide\_will") -- Called when the scene is on screen (but is about to go off screen) -- Insert code here to "pause" the scene -- Example: stop timers, stop animation, stop audio, etc. elseif ( phase == "did" ) then print("YYY\_hide\_did") -- Called immediately after scene goes off screen end end function scene:destroy( event ) local sceneGroup = self.view -- Called prior to the removal of scene's view -- Insert code here to clean up the scene -- Example: remove display objects, save state, etc. --myAudioPlayer = nil --audio.stop() --audio.rewind(1) flushTimers() --timersArray = nil print("YYY\_destroy\_did") end scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene )

by the way, this is how I remove the current scene
 

composer.removeScene("currentScene") composer.gotoScene("nextScene",effectOptions)

please help!
 

You have several things going on.

First, you should not remove the scene currently on the screen. You need to wait until you are in another scene then remove the scene you just came from or if memory is not a concern, remove it just before you go to it.

Next you have to use scene names to go to and remove scenes. Unless your scenes are named “currentScene.lua” and “nextScene.lua”, your composer.removeScene() and composer.gotoScene() commands are not going to work.

Timers, transitions, physics and Runtime events are not removed when scenes are removed. You’re responsible to stop them yourself. Normally you would do that in scene:hide(), but we have to figure out why that’s not happening. But you should as a best practice, start these things in scene:show()'s “did” phase. You don’t want your enemies firing at your player before the scene is on the screen. It looks like you’re doing these things in scene:create().

Now for why scene:hide() isn’t happening: I can only suspect it’s because you’re not successfully calling composer.gotoScene() to go to another scene. The code itself looks right.

Rob

now the hide event is getting fired :slight_smile: , what i did was not remove the scene where i’m now as you said… and it started to work

the problem now is with stopping timers, i stop them in ( scene will hide ) using this function
 

timersArray = {} function flushTimers()   for j=1,5 do     print("didCancelTimer "..j)     timer.pause(timersArray[j])     timer.cancel(timersArray[j])     timersArray[j] = nil   end end

this is how the timers get created.
 

 function onTimer( event )         local params = event.source.params         doSomething()       end       for i=1,5 do           timersArray[i] = timer.performWithDelay( 1000\*someTimeVar, onTimer )           timersArray[i].params = { n = i }       end

but the problem, when i leave the scene that has the timers, they are still ticking, the new scene that i move to removes the old one came from !!

how to solve ?

I would put in some print statements and make sure things are being called correctly.

what the ??

the timers are printed as stopped in the terminal, but they are still responding for the listener !!
 

Aug 11 04:45:50.565            [3] => table: 0x7fad064b7fe0 {
Aug 11 04:45:50.565                     [_time] => 26323.255
Aug 11 04:45:50.565                     [_count] => 2
Aug 11 04:45:50.565                     [_listener] => table: 0x7fad063813d0 {
Aug 11 04:45:50.565                                      *table: 0x7fad064b7dc0
Aug 11 04:45:50.565                                    }
Aug 11 04:45:50.565                     [_removed] => true
Aug 11 04:45:50.566                     [_expired] => true
Aug 11 04:45:50.566                     [params] => table: 0x7fad063813d0 {
Aug 11 04:45:50.566                                   [n] => 3
Aug 11 04:45:50.566                                 }
Aug 11 04:45:50.566                   }

I have created a test scene, and the test scene works great, but the original one don’t stop the timers.
 

----- import & setup local composer = require( "composer" ) local scene = composer.newScene() display.setStatusBar( display.DarkStatusBar ) local timersArray = {} function scene:create( event )     local sceneGroup = self.view          function timersArray:timer( event )           local params = event.source.params           print("testEvent : "..params.n)           --timer.cancel( event.source ) -- after 3rd invocation, cancel timer     end          for i=1,10 do           timersArray[i] = timer.performWithDelay( 1000\*i, timersArray )           timersArray[i].params = { n = i }     end          print("didConstructThisArray")     print\_r(timersArray)                     function onKeyEvent( event )     local message = "Key '" .. event.keyName .. "' was pressed " .. event.phase     print( message )     --if (event.keyName == "back") and (system.getInfo("platformName") == "Android") then     if ((event.keyName == "escape") and event.phase == "down" ) then                         print("Before!!!!!")           print\_r(timersArray)                      for i=1,10 do             timer.cancel( timersArray[i])           end           print("AFTER!!!!!")           print\_r(timersArray)                      return true     end end Runtime:addEventListener( "key", onKeyEvent )     -- Initialize the scene here     -- Example: add display objects to "sceneGroup", add touch listeners, etc. end -- "scene:show()" function scene:show( event )     local sceneGroup = self.view     local phase = event.phase     if ( phase == "will" ) then         -- Called when the scene is still off screen (but is about to come on screen)    elseif ( phase == "did" ) then         -- Called when the scene is now on screen         -- Insert code here to make the scene come alive         -- Example: start timers, begin animation, play audio, etc.     end end -- "scene:hide()" function scene:hide( event )     local sceneGroup = self.view     local phase = event.phase     if ( phase == "will" ) then         -- Called when the scene is on screen (but is about to go off screen)         -- Insert code here to "pause" the scene         -- Example: stop timers, stop animation, stop audio, etc.     elseif ( phase == "did" ) then         -- Called immediately after scene goes off screen     end end -- "scene:destroy()" function scene:destroy( event )     local sceneGroup = self.view     -- Called prior to the removal of scene's view     -- Insert code here to clean up the scene     -- Example: remove display objects, save state, etc. end --------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) --------------------------------------------------------------------------------- return scene

 

wait, this is the problem now :-

canceling the timers using the escape button like before works, i tried to apply it to my original scene and works great
but canceling the timers with a touch listener button fails !!

Q : why it only works when called from escape button ?

 

this is a bug in corona or what ???

 

You are using “timersArray” for two different purposes. One is an array that holds your timers and once as a function to cancel your timers. Perhaps change the function name to “cancelTimers” instead of “timersArray” and then maybe things are better. It seems like you’re trying to use timers like you would table events on objects. I don’t believe timer will work that way. It needs to be a straight up function.

Rob

You have several things going on.

First, you should not remove the scene currently on the screen. You need to wait until you are in another scene then remove the scene you just came from or if memory is not a concern, remove it just before you go to it.

Next you have to use scene names to go to and remove scenes. Unless your scenes are named “currentScene.lua” and “nextScene.lua”, your composer.removeScene() and composer.gotoScene() commands are not going to work.

Timers, transitions, physics and Runtime events are not removed when scenes are removed. You’re responsible to stop them yourself. Normally you would do that in scene:hide(), but we have to figure out why that’s not happening. But you should as a best practice, start these things in scene:show()'s “did” phase. You don’t want your enemies firing at your player before the scene is on the screen. It looks like you’re doing these things in scene:create().

Now for why scene:hide() isn’t happening: I can only suspect it’s because you’re not successfully calling composer.gotoScene() to go to another scene. The code itself looks right.

Rob

now the hide event is getting fired :slight_smile: , what i did was not remove the scene where i’m now as you said… and it started to work

the problem now is with stopping timers, i stop them in ( scene will hide ) using this function
 

timersArray = {} function flushTimers()   for j=1,5 do     print("didCancelTimer "..j)     timer.pause(timersArray[j])     timer.cancel(timersArray[j])     timersArray[j] = nil   end end

this is how the timers get created.
 

 function onTimer( event )         local params = event.source.params         doSomething()       end       for i=1,5 do           timersArray[i] = timer.performWithDelay( 1000\*someTimeVar, onTimer )           timersArray[i].params = { n = i }       end

but the problem, when i leave the scene that has the timers, they are still ticking, the new scene that i move to removes the old one came from !!

how to solve ?

I would put in some print statements and make sure things are being called correctly.

what the ??

the timers are printed as stopped in the terminal, but they are still responding for the listener !!
 

Aug 11 04:45:50.565            [3] => table: 0x7fad064b7fe0 {
Aug 11 04:45:50.565                     [_time] => 26323.255
Aug 11 04:45:50.565                     [_count] => 2
Aug 11 04:45:50.565                     [_listener] => table: 0x7fad063813d0 {
Aug 11 04:45:50.565                                      *table: 0x7fad064b7dc0
Aug 11 04:45:50.565                                    }
Aug 11 04:45:50.565                     [_removed] => true
Aug 11 04:45:50.566                     [_expired] => true
Aug 11 04:45:50.566                     [params] => table: 0x7fad063813d0 {
Aug 11 04:45:50.566                                   [n] => 3
Aug 11 04:45:50.566                                 }
Aug 11 04:45:50.566                   }

I have created a test scene, and the test scene works great, but the original one don’t stop the timers.
 

----- import & setup local composer = require( "composer" ) local scene = composer.newScene() display.setStatusBar( display.DarkStatusBar ) local timersArray = {} function scene:create( event )     local sceneGroup = self.view          function timersArray:timer( event )           local params = event.source.params           print("testEvent : "..params.n)           --timer.cancel( event.source ) -- after 3rd invocation, cancel timer     end          for i=1,10 do           timersArray[i] = timer.performWithDelay( 1000\*i, timersArray )           timersArray[i].params = { n = i }     end          print("didConstructThisArray")     print\_r(timersArray)                     function onKeyEvent( event )     local message = "Key '" .. event.keyName .. "' was pressed " .. event.phase     print( message )     --if (event.keyName == "back") and (system.getInfo("platformName") == "Android") then     if ((event.keyName == "escape") and event.phase == "down" ) then                         print("Before!!!!!")           print\_r(timersArray)                      for i=1,10 do             timer.cancel( timersArray[i])           end           print("AFTER!!!!!")           print\_r(timersArray)                      return true     end end Runtime:addEventListener( "key", onKeyEvent )     -- Initialize the scene here     -- Example: add display objects to "sceneGroup", add touch listeners, etc. end -- "scene:show()" function scene:show( event )     local sceneGroup = self.view     local phase = event.phase     if ( phase == "will" ) then         -- Called when the scene is still off screen (but is about to come on screen)    elseif ( phase == "did" ) then         -- Called when the scene is now on screen         -- Insert code here to make the scene come alive         -- Example: start timers, begin animation, play audio, etc.     end end -- "scene:hide()" function scene:hide( event )     local sceneGroup = self.view     local phase = event.phase     if ( phase == "will" ) then         -- Called when the scene is on screen (but is about to go off screen)         -- Insert code here to "pause" the scene         -- Example: stop timers, stop animation, stop audio, etc.     elseif ( phase == "did" ) then         -- Called immediately after scene goes off screen     end end -- "scene:destroy()" function scene:destroy( event )     local sceneGroup = self.view     -- Called prior to the removal of scene's view     -- Insert code here to clean up the scene     -- Example: remove display objects, save state, etc. end --------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) --------------------------------------------------------------------------------- return scene

 

wait, this is the problem now :-

canceling the timers using the escape button like before works, i tried to apply it to my original scene and works great
but canceling the timers with a touch listener button fails !!

Q : why it only works when called from escape button ?

 

this is a bug in corona or what ???

 

You are using “timersArray” for two different purposes. One is an array that holds your timers and once as a function to cancel your timers. Perhaps change the function name to “cancelTimers” instead of “timersArray” and then maybe things are better. It seems like you’re trying to use timers like you would table events on objects. I don’t believe timer will work that way. It needs to be a straight up function.

Rob