I recently commented on a post on the Corona Labs forum from a developer who was having a hard time with timers that were not canceled when a scene was changed. Now the Corona SDK already gives us methods for pausing, resuming, or even canceling active timers, but those methods are somewhat restricted in that you can only cancel one timer at a time, and you must refer to the timer by it’s handle to do so. Under the current system, it’s very easy to accidentally leave a timer running when you would rather pause or cancel all your timers, or at least a number of them.
In my comment on that forum post, I suggested that the original poster vote up a Corona SDK feature request for the timer library to receive an update akin to the “Transition 2.0” update from a few years ago, so that we would have the ability to pause/resume/cancel all active timers at once, or to pause/resume/cancel a subset of active timers by tagging them. I still think that’s worth doing, and if you’re reading this, then you should definitely do that! However, part of what I love about Corona is how we developers can roll our own solutions to these sorts of problems while we wait for Corona Labs to add new features or fix bugs – so I decided to do just that and “fix” the timer library to enable those requested features.
How To Use The Timer 2.0 Library
Updating the timer library to “timer 2.0” in your Corona project is as simple as these two steps:
- Download timer2.lua and place it in your project’s root directory.
- Require the library in your project by adding this one line of code, preferably near the top of your main.lua:
require("timer2")
By taking those steps, you have updated Corona’s built-in timer library to version 2.0. Note that your existing code will continue to work – version 2.0 is fully backwards-compatible with the current official timer APIs. But you also gain access to these new features:
- timer.performWithDelay() now accepts two new optional function arguments: tag and exclude:
- tag is a string that appends a tag to the created timer that can be used to pause, resume, or cancel all timers with the same tag at once. Defaults to nil.
- exclude is a boolean (true/false) parameter that, when set to true, excludes the timer from being impacted by timer.pause(), timer.resume(), or timer.cancel() calls that do not specifically target it by passing the timer’s handle or tag. Timers that are mission-critical and should always run should have their exclude parameter set to true. Defaults to false.
- These new arguments can be added in any order to the end of any existing timer.performWithDelay() call.
- As an example, the following code would create a timer with the tag “myTag” that is excluded from non-specific pause, resume, or cancel calls:
timer.performWithDelay(1000, myFunction, 1, "myTag", true)
- timer.pause(), timer.resume(), and timer.cancel() still work as before, but with the following new features:
- You can pause, resume, or cancel all active timers (unless they have their exclude parameter set to true) by calling timer.pause(), timer.resume(), or timer.cancel() with no arguments.
- You can pause, resume, or cancel all timers with a specific tag by passing the tag as a parameter. For example, the following code would pause all active timers with the tag “myTag”.
timer.pause("myTag")
I hope that my fellow Corona developers will find this unofficial library update to be useful. As with all Corona code I post on this site, the library is free to download, free to use, and you are free to modify it as you see fit. If you do make improvements you think others could use, please share in the comments, or contact me so I can update the library here on the site. Enjoy!
That’s exactly what I did with my project ๐
I did it in the same way with params: tag and exclude. Btw, thank for your codes
And more, I think you should discriminate the “tag” and “timerID” in timer.pause, timer.resume, timer.cancel.
Tag must be a string while timerID is a userdata ( table ). Make it clear is better :).
Sorry for my bad English ๐
I get an error in your timer2.lua file when I use timer.pause() with no arguments.
timer2.lua:101: attempt to concatenate local ‘timerID’ (a nil value)
I just added the line require(“timer2”) and I used timers as always..
Thanks
Hi @ltd:
Thanks for commenting! Yikes, I left a couple of print statements in the module from when I was testing it out, and yes – if you don’t pass an argument to timer.pause(), you’ll get a Runtime error because I’m trying to print the argument and forgot to convert it to a string. My bad! Those couple of print statements are actually not required, so I’ve removed them and updated the module for download. If you re-download it, you should be good to go. Or, if you want, just remove lines 101 & 104 from the old version. Thanks for catching my mistake!
I think that I love you <3
This is excellent and I thank you for the code and for saving me the hassle of trying to fix it or work around the limitation myself
Kudos!
thanks for the code. i added the require(“timer2”) on my page and called timer.cancel() to but nothing happened.
I am building a quiz app that works with timer. when the user clicks on the menu button, i want it to cancel the timer. kindly assist
First, thanks for your code, really helped out and solved a number of issues.
I did find that it didn’t quite perform as expected when I specified iterations greater than one and paused the timer between iterations, I found it would delete the timer so I could not resume (timeLeft was less than 0 for that iteration).
I modified your code slightly by modifying the line as follows, seems to work.
if timeLeft 0 or equals nil if iterations was set to 1.
Hope this helps someone,
Craig
what exactly did u change? i had the same problem but, even tho i thought i fixed it, it came to haunt me back later on
can you post some a code with your solution?
thank you!
Hi Ivan,
Craig’s fix has been incorporated into the module, which you can re-download and use (thanks, Craig!). The download link above now goes to the the timer2 repository on GitHub (I’m going to be distributing my modules via GitHub from now on). Thanks! ๐
Hello admin i see you don’t monetize your page. You can earn extra bucks easily,
search on youtube for: how to earn selling articles
Hi Jason,
Just dropping by to say thank you for the code!
This has just saved me quite a headache by not having to go back through all my code adding tags to pause timers – is rather efficient and really useful!
Makes me wonder why they do not update Corona simply to work this way.
Anyway, thanks again, and all the best to you.
Warm regards,
Nick
Hi Jason,
Just want to follow up my previous comment…I’ve had to pull your module out of my project. It was mishandling a cancel command specific to a particular timer and cancelling others, no errors, no warnings, nothing. Removed your module and immediately received a runtime error as would have expected initially. Simply don’t have time to document it all for you for the moment, nor fault-find your code. Thanks for the effort but am going back to using the vanilla Corona functions and additional work that entails. Shame really, one day I might be in a position to resolve, but not now – I need to finish my project. All the best,
Nick
Hi Nick,
Understood. No offense taken – you gotta do what works best for you. It’s hard for me to do any real diagnosis based on just a comment, but my guess is that the handle you were passing in to your `timer.cancel()` call was returning nil – which means even though you were calling `timer.cancel(some_handle)`, it was being interpreted as if you passed in `timer.cancel()` with no arguments, which means “cancel all timers.” If I had to guess, I’d say that you should wrap your problematic `timer.canel(some_timer)` call in a conditional, as in: `if some_timer ~= nil then timer.cancel(some_timer) end`, but that’s just a guess.
Anyways, good luck with your project, and I’m sorry the module created a pain point for you!
-Jason
Hi Jason,
Thanks for your very prompt reply. I’m glad no offense was taken as none was meant – you provided free code simply for the assistance of others! It seemed to be working fine, just found a knock-on effect that was not easy to locate or identify – exasperated by my “newbie” level of Corona and Lua. This is my first project – although easily my biggest, so I need to know exactly what I’m dealing with, as I’m sure you can understand. Thanks again – maybe one day I’ll be able to properly trap and resolve this for all of us.
All the very best,
Nick
Hi Jason,
Just wanted to update you. Have decided to continue to use your module as it would have been so much work to go back through my project making the necessary alterations. In the end I just commented out the timer.cancel code so that I still use the native command for this only – and will therefore receive errors as expected.
This was all during finding what I’m pretty sure is a bug in Corona SDK where removing a display object or setting it to nil was consistently cancelling existing transitions on (all) other completely unrelated objects! Wow the world of coding sure keeps me on my toes..anyway, just wanted to let you know, and thanks again for your recent feedback – and again for the module. Look out for my game in the not-too-distant future! Take care ๐ Nick