How to cancel a timer in the hide and destroy part of Composer

Im having issues trying to cancel a timer as it just keeps running when the scene is closed. I have the timer in the Scene Show event,

function scene:show( event ) local sceneGroup = self.view local phase = event.phase if phase == "will" then elseif phase == "did" then local text = display.newText( options ) local function generate(event) for row in db:nrows("SELECT quote from quotes ORDER BY RANDOM() LIMIT 1") do local result = row.quote text.text = result end end local timer = timer.performWithDelay( 2000, generate, 0 )

Then, in the Hide and Destroy events later on,

timer.cancel(timer)

I cant seem to stop the timer when the scene is closed. I tried inserting the timer into SceneGroup but it didnt like that.

Timer is local to the show function. You need a define timer with scene scope.

Interesting, how would I define a timer with scene scope? Ive been reading the Scene Management page, http://docs.coronalabs.com/guide/system/composer/index.html#management

You can just declare it outside of the scene functions. Here’s what I use (there are simpler methods, but this is mine):

local chestTimer = {} local function cancelchestTimers() local k, v for k,v in pairs(chestTimer) do timer.cancel( v ) v = nil; k = nil end chestTimer = nil chestTimer = {} --chestTimer[#chestTimer+1] = return cancelchestTimers end function scene:show( event ) local phase = event.phase if ( phase == "did" ) then chestTimer[#chestTimer+1] = timer.performWithDelay(75, function() -- do something here end, 0) end end function scene:hide( event ) local group = self.view local phase = event.phase if ( phase == "will" ) then elseif ( phase == "did" ) then cancelchestTimers() end end

Scenes are simple, but at the same time they are complex.  You have to have a grasp on scope (when variables/functions are visible to other functions), how modules are loaded and unloaded, and how events work.

To sum it up:

Code that’s not inside a function in a scene module gets executed once, when the module is initially required.  Your timer and the code to create the display.newText() fall into this category.

scene:create() gets called before scene’s are put on the screen.  You put things here needed to create the scene, such as your display.newText().

scene:show() is where you start timers.

scene:hide() is where you stop timers.

scene:destroy() is where you get rid of things like audio that you created in scene:create().   scene:create() and scene:destroy() are basically called in pairs (though unless the scene is never removed).  scene:show() and scene:hide() will always be called in pairs.

main.lua is never a scene.  But anything needed to initialize the app’s run, is typically done in main.lua.

In your example, I would put your “generate” function near the top, but not inside any other function.  Then in scene:show() (it will get called twice, once with a phase of “will” and once with a phase of “did”.  When you get the did phase then the scene is on screen, then you call your timer.

Your display.newText() is something that should be in scene:create() but since you need to reference it elsewhere (i.e. other functions) at the top of your scene do:

local text  – you probably should give it a more descriptive name

Then inside scene:create do:

    text = display.newText(…) – leave off the local here.

Then things will work as you expect.

Rob

Thanks Ill go ahead and try that. I did find the page for Composer http://docs.coronalabs.com/guide/system/composer/index.html a little  tricky sometimes about where to place items and have them function as intended, such as the aforementioned timer.

Timer is local to the show function. You need a define timer with scene scope.

Interesting, how would I define a timer with scene scope? Ive been reading the Scene Management page, http://docs.coronalabs.com/guide/system/composer/index.html#management

You can just declare it outside of the scene functions. Here’s what I use (there are simpler methods, but this is mine):

local chestTimer = {} local function cancelchestTimers() local k, v for k,v in pairs(chestTimer) do timer.cancel( v ) v = nil; k = nil end chestTimer = nil chestTimer = {} --chestTimer[#chestTimer+1] = return cancelchestTimers end function scene:show( event ) local phase = event.phase if ( phase == "did" ) then chestTimer[#chestTimer+1] = timer.performWithDelay(75, function() -- do something here end, 0) end end function scene:hide( event ) local group = self.view local phase = event.phase if ( phase == "will" ) then elseif ( phase == "did" ) then cancelchestTimers() end end

Scenes are simple, but at the same time they are complex.  You have to have a grasp on scope (when variables/functions are visible to other functions), how modules are loaded and unloaded, and how events work.

To sum it up:

Code that’s not inside a function in a scene module gets executed once, when the module is initially required.  Your timer and the code to create the display.newText() fall into this category.

scene:create() gets called before scene’s are put on the screen.  You put things here needed to create the scene, such as your display.newText().

scene:show() is where you start timers.

scene:hide() is where you stop timers.

scene:destroy() is where you get rid of things like audio that you created in scene:create().   scene:create() and scene:destroy() are basically called in pairs (though unless the scene is never removed).  scene:show() and scene:hide() will always be called in pairs.

main.lua is never a scene.  But anything needed to initialize the app’s run, is typically done in main.lua.

In your example, I would put your “generate” function near the top, but not inside any other function.  Then in scene:show() (it will get called twice, once with a phase of “will” and once with a phase of “did”.  When you get the did phase then the scene is on screen, then you call your timer.

Your display.newText() is something that should be in scene:create() but since you need to reference it elsewhere (i.e. other functions) at the top of your scene do:

local text  – you probably should give it a more descriptive name

Then inside scene:create do:

    text = display.newText(…) – leave off the local here.

Then things will work as you expect.

Rob

Thanks Ill go ahead and try that. I did find the page for Composer http://docs.coronalabs.com/guide/system/composer/index.html a little  tricky sometimes about where to place items and have them function as intended, such as the aforementioned timer.