You can actually write over one object’s variable reference and it will get garbage collected; It’s just not good practice because it leads to reading your own code badly and that leads to making mistakes.
For display object cleaning I create a named reference to a display group’s children on the group itself. That way, all I need to do is remove the group and set it’s own variable to nil. All the display objects are removed and their references in two lines.
Your scGraphic is not being inserted over and over because it is removed from display memory when you call display.remove(scGraphic) The variable reference needs to be set to nil, but you’re already doing that.
Ok, so as an example of how I write a scene, to keep everything tidy, here’s how I would write a button creation function:
-- file: buttonlib.lua local buttonlib = {} local function createButton( parent, title, x, y, callback ) parent = parent or display.currentStage local group = display.newGroup() group.class = "button" group.x, group.y = x, y parent:insert( group ) local text = display.newText{ parent=group, text=title, fontSize=32, x=0, y=0 } group.text = text local bg = display.newRoundedRect( group, 0, 0, text.width\*1.1, text.height\*1.2, 15 ) bg.fill = {0,1,0} function group:touch(e) return true end group:addEventListener( "touch", group ) function group:tap(e) if (callback) then callback(e) end return true end group:addEventListener( "tap", group ) return group end buttonlib.createButton = createButton return buttonlib
So, obviously, there’s a lot missing (decent colour settings, for one) but this demonstrates how I reference objects with other objects. I would never, ever keep a reference in another piece of code to the text object created inside this function. That would cause memory leaks but it is also unnecessary because, if I have a reference to this button I can just call it’s .text object.
Removing the parent group (assuming that the scene’s view is passed as the first parameter) will remove all display objects created within this function and, because the only variable references to those objects are within this function or stored against the ‘group’ variable, they are garbage collected too, when the scene’s view is removed.
I do not explicitly remove touch or tap listeners because they are local listeners. This is explained in the “important” block, here:
http://docs.coronalabs.com/daily/guide/events/detectEvents/index.html#registering-events
If I were to create a scene which uses this button, I would do something like this (missing lots of code here):
local buttonlib = require("buttonlib") local composer = require("composer") local scene = composer.newScene() local sceneGroup local function gotoMenu(e) composer.gotoScene( "menu", { time=350, effect="fade" } ) end function scene:create( event ) sceneGroup = self.view sceneGroup.aMenuButton = buttonlib.createButton( sceneGroup, "Go to Menu", 100, 100, gotoMenu ) end function scene:show( event ) if (event.phase == "will" ) then sceneGroup.aMenuButton.alpha = 0 elseif (event.phase == "did" ) then transition( sceneGroup.aMenuButton, { time=350, alpha=1 } ) end end function scene:hide( event ) if (event.phase == "will" ) then transition( sceneGroup.aMenuButton, { time=350, alpha=0 } ) elseif (event.phase == "did" ) then end end function scene:destroy( event ) sceneGroup = nil end scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) return scene
If I were listening to an object that I created myself, for example for custom events or events fired on the Runtime object, I would explicitly remove them in the hide() function’s “will” phase. If the createButton() function had any listeners for custom events it would benefit from having a “scene” parameter. It could then listen for the end of a scene and perform it’s own removeEventListener operations at the appropriate time.