One of the most confusing aspects of Corona’s storyboard API is the purging and/or removal of scenes. What’s the difference between purging and removing? What does it mean to “purge” a scene anyway? Those are just a few of the many questions we receive often.
Today, I’m going to attempt to clear up the confusion by first giving you a high-level overview of what’s going on behind-the-scenes when purging and removal goes on, and also show you a few examples along the way.
Memory Consumption
When a Corona display object is created, it takes up both texture memory (graphics) as well as Lua memory (data, such as tables and variables). When modules are loaded, such as scene modules, it is simply a table that is stored in memory. It is often quicker to load things from memory, but having too many things in memory at once can also impede performance. Because of this constant balancing act, we decided it’s best for you to have full control of what should remain in memory, as well as when things should be unloaded/freed from memory—afterall, every app is unique in some way.
With that in mind, here’s a basic overview of what purging and removing is in regards to storyboard scenes:
Purging is removing only the display objects from the scene, to include the scene’s display group (thus freeing up texture memory). However, if the scene is represented by an external module, the module will still remain in memory, as well as any custom variables you attached to the scene object.
Removing a scene means removing everything (display objects, and Lua objects). The result is freed texture memory as well as Lua memory.
So why purge at all?
If there is a scene you can foresee the user potentially going back and forth to, but are in a scene that requires as much texture memory as possible, then it’s usually better to purge the other scene that will be soon reloaded (since the module remains in memory).
For example, let’s say you are creating an action arcade game. It uses lots of physics, and has tons of objects all moving at fast speeds—needless to say, the game scene requires as much texture memory as possible.
In the corner of the game screen is a pause button, that loads the “pausegame” scene whenever it is pressed. Since the user may be switching to this scene often, it might be a good idea to simply purge the scene (to regain as much texture memory as possible), but leave the “pausegame.lua” module in memory since the user will potentially keep coming back to the scene.
Functions for Purging
There are two storyboard functions that handle scene purging:
The first function takes a single argument, sceneName, that corresponds to the scene you want purged. If the scene-to-be-purged corresponds to an external module, it is the module name (minus the “.lua” extension).
Since scene purging will “destroy” the display objects that correspond to the scene, it is best to call this function once the scene is no longer being displayed on-screen. The event that corresponds to that best is “didExitScene“.
Here’s an example of a scene that purges itself when it has fully exited the screen:
-- scene1.lua
local storyboard = require "storyboard"
local scene = storyboard.newScene()
-- createScene event simply creates a background image
function scene:createScene( event )
local bg = display.newImage( self.view, "background.png" )
end
scene:addEventListener( "createScene" )
function scene:didExitScene( event )
storyboard.purgeScene( "scene1" )
end
scene:addEventListener( "didExitScene" )
return scene
Now, let’s say you’re transitioning from a scene to menu.lua. You can get to menu.lua from several other scenes, so here’s an example of how to purge the previous scene, even if you do not know exactly where the user came from:
-- menu.lua
local storyboard = require "storyboard"
local scene = storyboard.newScene()
-- createScene event simply creates a background image
function scene:createScene( event )
local bg = display.newImage( self.view, "background.png" )
end
scene:addEventListener( "createScene" )
function scene:enterScene( event )
local prior_scene = storyboard.getPrevious()
storyboard.purgeScene( prior_scene )
end
scene:addEventListener( "enterScene" )
return scene
You can also use storyboard.purgeAll() instead to purge all scenes, except for the currently active scene. Whenever a scene is purged, a “destroyScene” event will be dispatched in case you need to do any last-minute actions, such as remove Runtime listeners you added in the scene, or anything else.
Functions for Removing
There are two storyboard functions that handle scene removal. When either of the two functions below are called, the scene will first be purged before being removed.
The first function takes a single argument, sceneName, that corresponds to the scene you want removed. If the scene-to-be-removed corresponds to an external module, it is the module name (minus the “.lua” extension).
Since each scene is purged before being completely removed, a “destroyScene” event will be dispatched on each scene that is removed.
Automatic Purging
On iOS, by default, storyboard will automatically purge the least-recently-used scene when the OS issues a “Low Memory Warning”. If you do not want this automatic behavior to occur, you can use the storyboard.disableAutoPurge property to control this behavior:
storyboard.disableAutoPurge = true
The default value is false, so if you explicitly set it to true, then you must be sure to purge scenes that you no longer need or your app’s texture memory consumption will continue to rise higher and higher as new scenes are loaded. If you are developing for Android, you’ll need to do this since the automatic purging does not occur on Android devices.
If you do not want to deal with manually purging scenes, but do not like the automatic scene purging behavior, then you can set storyboard.purgeOnSceneChange property to true, and all scenes will be purged every time you change scenes (except for the scene you are switching to).
For more information, see the storyboard.* API documentation.




Rob Miracle
Can we get a storyboard.removeOnSceneChange property?
A frequent problem I run into is that I will have state variables set in a scene and when I return to it later, these don’t always get reset properly. Yes, it’s bad programming on my part, but it’s easier to remove the scene and restart it rather than to try and track down every one of the little buggers and reset them. I guess I will make it my standard to drop a removeScene() call into my didExitScene() event.. That may be a cleaner way of handling it.
Jen Looper
I’m with Rob, I have had loads of problems with storyboard scenes that need to be refreshed. What’s the best way to refresh a scene, for example after I set a variable in main.lua, a scene that uses that variable could listen for that change and refresh “behind the scenes”, without being obliged to purge it and then load it up again?
Fito (nml)
I’m with you guys! I always get problems when trying to reset a scene. Some things get lost or whatever. It might be bad programming as rob wrote, but i still get the feeling that something could be done in order to clear this up. I’m glad this tutorials are done!
By the way, would purging a scene be the same as calling display.remove(object) on every display object created on that scene? Would that remove all listeners, timers and transitions associated with those objects?
Jen Looper
so glad it’s not just me!!!
Facada
Thank you for this article.
I think that it’s still missing a storyboard tutorial for beginners. As a beginner myself, and not having any experience with director, I’m having some difficulties in understanding the basics of storyboard, specially in what concerns memory management.
Greg
@Jonathan – would you be able to confirm we are on the right track in this forum post regarding use of widgets in storyboard, and particular the listener aspects? https://developer.coronalabs.com/forum/2012/07/31/any-update-widget-support-within-storyboard-coronalabs#comment-117812 . I guess I want to understand storyboard enterScene vs createScene and how it appears that widgets don’t lend themselves to this Corona strategy as you have to set up the listener for a widget when the widget is created…
Cosmin
Hy, I have the class thegame.lua. When I reload the class, how I see, the old instance it’s not deleted. I have an listener for collision, and after reload class, it’s called the method from old instance…I tested this with another copy class. I loaded first thegame.lua than testthegame.lua(the copy, with same functions) and the collision function was called from first class….
how can I delete the old one? the game it’s implemented with storyboard. I tried to purgeScene/removeScene on exit function called(exit from screen, not from app) but nothing…pls help
dellos
I’m not sure if “enterScene” event if pass after scene transition has finished.
–in scene 1
function scene:createScene( event )
local sgroup = self.view
btt = ui.newButton({default = “a.png”, over =”b.png”})
btt._onEvent = function() storyboard.gotoScene(“scene2″,”slideLeft”,5000) —> create error
end
sgroup:insert(btt)
end
–in scene2
function scene:enterScene(event)
print( “2: enter scene event” ———-> this line print twice ???
storyboard.purgeScene(“scene1″)
end
if time effect to lagre enter scene event seem pass immediately . i can see scene1 had purge while scene2 have transiting. ??
is that buge or I make worng some where ??
dellos
if don’t use ui.lua , it ok. but why? somebody could help me explain ???
dellos
sory but i had findout. in ui , onEvent call twice
). i was forgot it.