Quick question about composer.removeScene

Just a very quick question…

I have a scene (scene1) in my app that is only ever used once and non of the assets are reused either, so once composer has called the next scene I want to call composer.removeScene( “scene1” ) to free the memory that was used.

In the scene:destroy  function for scene1 do I manually have to remove every display object from the scene and nil them, or is there an easier (and quicker) way? Or have I misunderstood it altogether?

If its native control then you will have to manually remove each individually. (I read it from the forum.)

However, i got the problem where i remove each native.textfield in exitScene, but the textfield still remains when next scene appears.

==========================================================

MY CODE:

function scene:exitScene( event )

    if _textBox_Email then

    _textBox_Email:removeEventListener( “userInput”, textListener_textBox_Email )

        _textBox_Email:removeSelf()

        _textBox_Email = nil    

    end

end

==========================================================

i did a print of the textfield’s value in exitScene and it returns nil which means it never hit the removeSelf part. But if I don’t do the checking it gives me the error:

?: in function ‘dispatchEvent’

?: in function ‘?’

?: in function ‘gotoScene’

Can someone teach me how to properly remove native control from current scene before go to next scene?

Thank you!

Do you have a scope error?  Is it by any chance local to  your enterScene() function?

I local them in createScene. I tried move them outside the function then it doesn’t work.

here is my entire code please take a look for me. Thank you! Appreciate your help Rob.

-Edwin

==============================================================================================

local storyboard = require( “storyboard” )

local scene = storyboard.newScene()

display.setDefault( “background”,100/255,200/255,200/255)

storyboard.removeAll()

– Called when the scene’s view does not exist:

function scene:createScene( event )

–DECLARE CONTROL

local json = require “json”

local dataURL = "http://goldendehon.com/durham/latest.php"

local _hiddenField_Email = “”

local _hiddenField_Password = “”

local _textBox_Email = native.newTextField( display.contentCenterX, display.contentCenterY-28, 280, 25 )

_textBox_Email.font = native.newFont( native.systemFont, 20 )

_textBox_Email.InputType = “email”

_textBox_Email.placeholder = “Email”

local _textBox_Password  = native.newTextField( display.contentCenterX, display.contentCenterY, 280, 25 )

_textBox_Password.font = native.newFont( native.systemFont, 20 )

_textBox_Password.isSecure = true

_textBox_Password.placeholder = “Password”

local _button_SubmitLogin = display.newText( “Get Data”,display.contentCenterX,display.contentCenterY+35,“Helvetica”,48 )

–DECLARE FUNCTION

local function textListener_textBox_Email (event)

   if  ( event.phase == “submitted” or event.phase == “ended” ) then

         _hiddenField_Email = event.target.text

   end

end

local function textListener_textBox_Password (event)

   if  ( event.phase == “submitted” or event.phase == “ended” ) then

         _hiddenField_Password = event.target.text

   end

end

local options =

{

   effect = “fade”,

   time = 10000

   --params = { var1 = “custom”, myVar = “another” }

}

–download data to temp file, and read from file

– load a text file and return it as a string

local function loadTextFile( filename, base )

– set default base dir if none specified

if not base then base = system.ResourceDirectory; end

local path = system.pathForFile( filename, base )

local contents

– io.open opens a file at path. returns nil if no file found

local file = io.open( path, “r” )

if file then

  – read all contents of file into a string

  contents = file:read( “*a” )

  io.close( file ) – close the file after using it

end

return contents

end

local function getNewData()

if _hiddenField_Email == ‘’ or _hiddenField_Password == ‘’ then

native.showAlert( “Error”, “Please enter email and password!”, {“OK”})

else

local function newDataListener(event)

if (event.isError) then

print (“Error - no connection.”)

native.showAlert( “Error”, “Error - no connection.”, {“OK”})

else

local t = loadTextFile(“latest.txt”,system.TemporaryDirectory)

if t:sub(1,7) == "Error: " then

native.showAlert(“Error”,t,{“OK”})

else

t = json.decode( t )

if #t > 0 then

print ("Number of records: " … tostring(#t))

for v = 1, #t do 

print (t[v][“BusinessName”])

end

else

print (“No new record found!”)

native.showAlert( “Error”, “No new record found!”, {“OK”})

end

storyboard.gotoScene( “controlPanel”, “slideLeft”,8000 )

end

end

end

–local settings = {username=“edwin@email.com”,password=“pword”}

local settings = {username=_hiddenField_Email ,password=_hiddenField_Password}

local params = {}

params.body = “u=” … settings.username … “&p=” … settings.password … “&q=select * from bizlicense order by PrimaryNAICSText asc”

network.download( dataURL, “POST”, newDataListener, params,“latest.txt”,system.TemporaryDirectory)

end

end

_button_SubmitLogin:addEventListener(“tap”,getNewData)

_textBox_Email:addEventListener( “userInput”, textListener_textBox_Email )

_textBox_Password:addEventListener( “userInput”, textListener_textBox_Password)

end

– Called immediately after scene has moved onscreen:

function scene:enterScene( event )

end

– Called when scene is about to move offscreen:

function scene:exitScene( event )

    if _textBox_Email then

print(“Exiting…”)

    _textBox_Email:removeEventListener( “userInput”, textListener_textBox_Email )

        _textBox_Email:removeSelf()

        _textBox_Email = nil

    else

    print(“Not Exiting…”)    

    end

    native.setKeyboardFocus(nil)

–_textBox_Password

–_button_SubmitLogin

end

– Called prior to the removal of scene’s “view” (display group)

function scene:destroyScene( event )

end

– “createScene” event is dispatched if scene’s view does not exist

scene:addEventListener( “createScene”, scene )

– “enterScene” event is dispatched whenever scene transition has finished

scene:addEventListener( “enterScene”, scene )

– “exitScene” event is dispatched before next scene’s transition begins

scene:addEventListener( “exitScene”, scene )

– “destroyScene” event is dispatched before view is unloaded, which can be

– automatically unloaded in low memory situations, or explicitly via a call to

– storyboard.purgeScene() or storyboard.removeScene().

scene:addEventListener( “destroyScene”, scene )

return scene

==============================================================================================

Move these two lines outside of createScene just after or before the storyboard.removeAll()

local _hiddenField_Email = “”

local _hiddenField_Password = “”

Then you should be fine.

Rob

Thanks Rob for your prompt reply.

So i tried move the _hiddenFIeld out after the storyboard.removeAll(), nothing changes.

However, if I moved out all the local declaration outside the createScene after  storyboard.removeAll() then it works. 

Does it mean that I always declare controls and functions outside the function scene:xxxxx and only put the :addEventListener to the scene i want to use it??

-Edwin

You need to understand how code blocks work with local.  If you have a function:

function doSomething()

     local myVariable = 10

     print(myVariable)

end

doSomething()

The function runs, creates a variable named myVariable that only doSomething() knows about.  If you did this:

function doSomething()

     local myVariable = 10

end

doSomething()

print(myVariable)

In this case, myVariable has not been defined, so it tries to access a global variable named myVariable which is nil.

In your case, it’s perfectly fine to have things local inside of createScene() as long as you understand that they can only be seen within createScene.

If you need a variable that both  createScene() and exitScene() (or enterScene() ) need, then you need to make sure they are scoped either at a higher block (i.e. putting them at the top) which creates something called an *upvalue*, or add it to the scene’s object as a member.

Upvalues are okay, but there are a limit of 60 per module.   You could also in createScene do:

self.myVariable = “something”

Then in exitScene you would have self.myVariable available to you as well.  The only draw back here is you have to avoid using names that would stomp on existing things in the scene.object.  If you’re going to go this route, the suggestion is to use a table called “state” and then add your members there:

self.state = {}

self.state.myVariable = “something”

This tutorial might be helpful:
http://omnigeek.robmiracle.com/2011/10/14/understanding-scope-for-beginning-programmers/

Rob

Thank you Rob!! Appreciate your help!!!

-Edwin

If its native control then you will have to manually remove each individually. (I read it from the forum.)

However, i got the problem where i remove each native.textfield in exitScene, but the textfield still remains when next scene appears.

==========================================================

MY CODE:

function scene:exitScene( event )

    if _textBox_Email then

    _textBox_Email:removeEventListener( “userInput”, textListener_textBox_Email )

        _textBox_Email:removeSelf()

        _textBox_Email = nil    

    end

end

==========================================================

i did a print of the textfield’s value in exitScene and it returns nil which means it never hit the removeSelf part. But if I don’t do the checking it gives me the error:

?: in function ‘dispatchEvent’

?: in function ‘?’

?: in function ‘gotoScene’

Can someone teach me how to properly remove native control from current scene before go to next scene?

Thank you!

Do you have a scope error?  Is it by any chance local to  your enterScene() function?

I local them in createScene. I tried move them outside the function then it doesn’t work.

here is my entire code please take a look for me. Thank you! Appreciate your help Rob.

-Edwin

==============================================================================================

local storyboard = require( “storyboard” )

local scene = storyboard.newScene()

display.setDefault( “background”,100/255,200/255,200/255)

storyboard.removeAll()

– Called when the scene’s view does not exist:

function scene:createScene( event )

–DECLARE CONTROL

local json = require “json”

local dataURL = "http://goldendehon.com/durham/latest.php"

local _hiddenField_Email = “”

local _hiddenField_Password = “”

local _textBox_Email = native.newTextField( display.contentCenterX, display.contentCenterY-28, 280, 25 )

_textBox_Email.font = native.newFont( native.systemFont, 20 )

_textBox_Email.InputType = “email”

_textBox_Email.placeholder = “Email”

local _textBox_Password  = native.newTextField( display.contentCenterX, display.contentCenterY, 280, 25 )

_textBox_Password.font = native.newFont( native.systemFont, 20 )

_textBox_Password.isSecure = true

_textBox_Password.placeholder = “Password”

local _button_SubmitLogin = display.newText( “Get Data”,display.contentCenterX,display.contentCenterY+35,“Helvetica”,48 )

–DECLARE FUNCTION

local function textListener_textBox_Email (event)

   if  ( event.phase == “submitted” or event.phase == “ended” ) then

         _hiddenField_Email = event.target.text

   end

end

local function textListener_textBox_Password (event)

   if  ( event.phase == “submitted” or event.phase == “ended” ) then

         _hiddenField_Password = event.target.text

   end

end

local options =

{

   effect = “fade”,

   time = 10000

   --params = { var1 = “custom”, myVar = “another” }

}

–download data to temp file, and read from file

– load a text file and return it as a string

local function loadTextFile( filename, base )

– set default base dir if none specified

if not base then base = system.ResourceDirectory; end

local path = system.pathForFile( filename, base )

local contents

– io.open opens a file at path. returns nil if no file found

local file = io.open( path, “r” )

if file then

  – read all contents of file into a string

  contents = file:read( “*a” )

  io.close( file ) – close the file after using it

end

return contents

end

local function getNewData()

if _hiddenField_Email == ‘’ or _hiddenField_Password == ‘’ then

native.showAlert( “Error”, “Please enter email and password!”, {“OK”})

else

local function newDataListener(event)

if (event.isError) then

print (“Error - no connection.”)

native.showAlert( “Error”, “Error - no connection.”, {“OK”})

else

local t = loadTextFile(“latest.txt”,system.TemporaryDirectory)

if t:sub(1,7) == "Error: " then

native.showAlert(“Error”,t,{“OK”})

else

t = json.decode( t )

if #t > 0 then

print ("Number of records: " … tostring(#t))

for v = 1, #t do 

print (t[v][“BusinessName”])

end

else

print (“No new record found!”)

native.showAlert( “Error”, “No new record found!”, {“OK”})

end

storyboard.gotoScene( “controlPanel”, “slideLeft”,8000 )

end

end

end

–local settings = {username=“edwin@email.com”,password=“pword”}

local settings = {username=_hiddenField_Email ,password=_hiddenField_Password}

local params = {}

params.body = “u=” … settings.username … “&p=” … settings.password … “&q=select * from bizlicense order by PrimaryNAICSText asc”

network.download( dataURL, “POST”, newDataListener, params,“latest.txt”,system.TemporaryDirectory)

end

end

_button_SubmitLogin:addEventListener(“tap”,getNewData)

_textBox_Email:addEventListener( “userInput”, textListener_textBox_Email )

_textBox_Password:addEventListener( “userInput”, textListener_textBox_Password)

end

– Called immediately after scene has moved onscreen:

function scene:enterScene( event )

end

– Called when scene is about to move offscreen:

function scene:exitScene( event )

    if _textBox_Email then

print(“Exiting…”)

    _textBox_Email:removeEventListener( “userInput”, textListener_textBox_Email )

        _textBox_Email:removeSelf()

        _textBox_Email = nil

    else

    print(“Not Exiting…”)    

    end

    native.setKeyboardFocus(nil)

–_textBox_Password

–_button_SubmitLogin

end

– Called prior to the removal of scene’s “view” (display group)

function scene:destroyScene( event )

end

– “createScene” event is dispatched if scene’s view does not exist

scene:addEventListener( “createScene”, scene )

– “enterScene” event is dispatched whenever scene transition has finished

scene:addEventListener( “enterScene”, scene )

– “exitScene” event is dispatched before next scene’s transition begins

scene:addEventListener( “exitScene”, scene )

– “destroyScene” event is dispatched before view is unloaded, which can be

– automatically unloaded in low memory situations, or explicitly via a call to

– storyboard.purgeScene() or storyboard.removeScene().

scene:addEventListener( “destroyScene”, scene )

return scene

==============================================================================================

Move these two lines outside of createScene just after or before the storyboard.removeAll()

local _hiddenField_Email = “”

local _hiddenField_Password = “”

Then you should be fine.

Rob

Thanks Rob for your prompt reply.

So i tried move the _hiddenFIeld out after the storyboard.removeAll(), nothing changes.

However, if I moved out all the local declaration outside the createScene after  storyboard.removeAll() then it works. 

Does it mean that I always declare controls and functions outside the function scene:xxxxx and only put the :addEventListener to the scene i want to use it??

-Edwin

You need to understand how code blocks work with local.  If you have a function:

function doSomething()

     local myVariable = 10

     print(myVariable)

end

doSomething()

The function runs, creates a variable named myVariable that only doSomething() knows about.  If you did this:

function doSomething()

     local myVariable = 10

end

doSomething()

print(myVariable)

In this case, myVariable has not been defined, so it tries to access a global variable named myVariable which is nil.

In your case, it’s perfectly fine to have things local inside of createScene() as long as you understand that they can only be seen within createScene.

If you need a variable that both  createScene() and exitScene() (or enterScene() ) need, then you need to make sure they are scoped either at a higher block (i.e. putting them at the top) which creates something called an *upvalue*, or add it to the scene’s object as a member.

Upvalues are okay, but there are a limit of 60 per module.   You could also in createScene do:

self.myVariable = “something”

Then in exitScene you would have self.myVariable available to you as well.  The only draw back here is you have to avoid using names that would stomp on existing things in the scene.object.  If you’re going to go this route, the suggestion is to use a table called “state” and then add your members there:

self.state = {}

self.state.myVariable = “something”

This tutorial might be helpful:
http://omnigeek.robmiracle.com/2011/10/14/understanding-scope-for-beginning-programmers/

Rob

Thank you Rob!! Appreciate your help!!!

-Edwin