Hey folks. I’ve run into an interesting problem (which may seem simple on first glance).
I already filed a bug (38656) for this, but I like to self-solve as much as possible and I’m guessing someone out there may have a nice solution or at least some ideas.
Note: I did find a workaround that will work universally, but I’m still hoping Corona will fix this weird behavior and/or provide a ‘valid object’ test. See my third post below for the workaround.
Problem Recipe
- Create an object
- Add a physics body.
- Add enterFrame listener ‘method’ to body.
- Start Listener
- Using timer.performWithDelay() destroy object after a short duration.
Problem That Occurs
On the first ‘enterFrame’ after the timer fires:
- self.removeSelf still points to a function
- self.setLinearVelocity (and all other physics methods) is nil
On the second ‘enterFrame’ after the timer fires:
- self.removeSelf is nil
- self.setLinearVelocity (and all other physics methods) is nil
So, why is this a problem?
- Corona does not provide a ‘is valid’ test for objects.
- The generally accepted way to test if an object is valid is by checking for the existence of a ‘removeSelf’ function.
Workarounds?
Some of you may be thinking one of the following things:
- Workaround 1 - “Duh, Ed. Just set the object to nil after removing it.”
- Workaround 2 - “Um, you spelled out the solution in your problem definition. Check for the presence of a physics method like ‘setLinearVelocity’ instead!”
Why Workaround Are No Good
- Workaround 1 - Actually this is good, but only in the same scope. For any case where an object may be removed in a different scope, the solution fails.
- Workaround 2 - Yes, this is workable and solves the problem, BUT it is not universal. I need a univesal fix. (Thus the bug filing).
So, if anyone out there has solutions or ideas please share them. Meanwhile, here is some code to show the problem (you’ll need to look at the console output to see the issue)
local physics = require "physics" physics.start() physics.setGravity( 0, 0 ) local testObj = display.newCircle( 100, 100, 10 ) physics.addBody( testObj ) timer.performWithDelay( 1000, function() display.remove( testObj ) print("Object destroyed @ " .. tostring( system.getTimer())) end ) testObj.enterFrame = function( self, event ) if( self.removeSelf == nil ) then Runtime:removeEventListener( "enterFrame", self ) print( "Ignoring " .. tostring( self ), tostring( self.setLinearVelocity ), system.getTimer(), "\n-----------" ) return end print( tostring( self ), tostring( self.setLinearVelocity ), system.getTimer(), "\n-----------" ) end Runtime:addEventListener( "enterFrame", testObj )