Need to :remove a running timer before setting it again with .new?

Back when I was new to Lua and Playdate I was having some kind of problem with re-using a running timer, having the original callback AND the new one both trigger. I don't recall the exact symptoms anymore.

What I wanted was to re-assign the same timer variable and have the old instance—IF ANY—just be gone: never to complete, never to execute the old callback.

So I ended up with this kind of structure ALL over my code: testing for a timer's existence every time I try to use it, and removing it before re-assigning:

local eventTimer = nil

function setEventTimer()
	if eventTimer ~= nil then 
		eventTimer:remove() -- (NEEDED?)
	end
	
	eventTimer = pd.timer.new(2000, doEvent)
end

Is that extra step really necessary? Or should I be OK (and responsible with RAM) just re-assigning eventTimer = pd.timer.new without removing the already-running timer?

(Removing it means also first checking if it exists every time... since :remove throws an error if it doesn't.)

Thanks in advance! I have a ton of timers in Outside Parties, and skipping that would clean up the code nicely!

Yes, it is necessary, as there would be no way for the original timer to know you had reassigned your variable to a newly-created timer.

You could create a convenience function to make the removal logic a bit less verbose. Something like

local function replaceTimer(oldTimer, duration, callback)
	oldTimer:remove()
	oldTimer = playdate.timer.new(duration, callback)
end

However, I wonder if it would make more sense to call playdate.timer:reset() and adjust the duration and timerEndedCallback properties, rather than re-assigning your variable to a new timer?

You could create a function for that too:

function playdate.timer:resetWithDurationAndCallback(duration, callback)
	self:reset()
	self.duration = duration
	self.timerEndedCallback = callback
end

That way other aspects of the timer would be preserved (for instance, if you had set repeats to true) if that's desirable.

(just to note: you can call :remove() again on an already-removed timer, just not on nil, because you can't call a method on nil)

2 Likes

Thanks! Yeah—that check for nil seems to be needed just for the moment that FIRST creates a given timer.