storyboard GLOBALS

okay so im hearing tutorials and corona developers saying that we should “avoid global variables”

the question is. . how bout when im using the “STORYBOARD” instead of “director” . . the variables inside “createscene” function cannot be accessed when i try to manipulate them inside “enterscene” function. .so i have no other choice but use global variables…  .is there any other way to avoid this???

example:

function scene:createScene( event )
    local sceneGroup = self.view
    
    local myImage = display.newImage(“image.png”)   

end

function scene:enterScene( event )
    local scene = self.view
   

 transition.to(myImage,{timer =1000,x =10})
    
end

–now this is just a sample…but i know that i will get an error here… “enterScene” will consider “myImage” as ‘nil’ even though i declared it inside the “createScene” . . so the only solution is remove the ‘local’ before the variable “myImage” in the createScene… making it a global variable

Hi,

I am also new to storyboard (coming from Director) and also struggling on the same issue. In your case, I think you can use local myImage at the top of the module (before create) and it should accessible from both createScene() an enterScene()

Again, i am new to this so please take my suggestion with a grain of salt :slight_smile:

Hope this help.

Mo

Hey guys.  There are two ways to solve this:

1. Use file level locals (GOOD):

local storyboard = require( "storyboard" ) local scene = storyboard.newScene() local myImage -- Now visibile to createScene() and enterScene()  function scene:createScene( event )        local sceneGroup = self.view    myImage = display.newImage( sceneGroup, "image.png" ) end function scene:enterScene( event )    local sceneGroup = self.view    transition.to( myImage, { timer =1000, x =10 } )  end     

2. Use the group that storyboard gives you and attach a ‘variable collector’.  This will be visible in all ** of this scene’s **** functions, and will be automatically removed when  storyboard  destroys the scene (BETTER in many cases).**

local storyboard = require( "storyboard" ) local scene = storyboard.newScene() function scene:createScene( event )    local sceneGroup = self.view    local myData = {}    sceneGroup.data = myData    myData.myImage = display.newImage( sceneGroup, "image.png") end function scene:enterScene( event )    local sceneGroup = self.view    local myData = sceneGroup.data    transition.to(myData.myImage, { timer =1000, x =10 } )  end   

[hr]

Note: I also made some corrections to the original code:

  1. You created a newImage(), but did not insert it into sceneGroup.  If you don’t do this, that scene and storyboard will not manage it for you.  It gets placed in the top-level group by default and will not be removed or hidden if the scene changes.

  2. In one scene: callback, you called the group ‘sceneGroup’ and in the other you called it ‘scene’.

   2a. Calling it scene was wrong as that is the name you’re using for your local ‘scene’ as created/provided by storyboard.

  2b. Whatever you call the variable ‘event.view’ when you place it in a local, always use the same name in your callbacks or it will be very confusing later.

@roaminggamer

@LairdGames

PERFECT!!! your answers are absolutely appreciated! thankx guyz! :)) especially roaminggamer… suggestion #2 is somehow new and id like to try it! thnx a bunch! :))

Ed’s #1 is the best method if the variables you need are to be used only within that scene.  It is the proper way to scope your variables for use.

Ed’s #2 works if you need to pass data between scenes, though as we talked about here:

http://www.coronalabs.com/blog/2013/05/28/tutorial-goodbye-globals/

adding things to the storyboard table might be safe today, but there is no promise that we won’t add features in the future that might use the name you choose (myData is probably pretty safe, but…)   The blog post above, shows how to create a data module that you can include in each scene (or other module) that makes data available between scenes in a future safe, non-global way. 

No problem!

@roaminggamer: Thanks for the option 2! I was wondering about option 1: 

local myImage – Now visibile to createScene() and enterScene()

No p I will assume that myImage will be garbage collected when the scene is removed? For option 2 it seems that you need to preface each variable with the mydata (dot notation) but it really look good to use. Would you put all the variables you need into mydata in CreateScene() then use them in the enterScene()?

Thanks again.

Mo

EDIT: Thanks Rob for the clarification. It is very helpful. Yes I already the technique you show on that link (great stuff by the way) So I think I will use option 1 (locals variables in the main chunk) when I only need to use those variables in the same scene.

@Mo,

Hi.  The only problem  with solution #1 is that if you do not explicity clear ‘myImage’ (i.e. set to nil)in destroyScene, LUA will not garbage collect it till the module is removed from memory, which may never happen.

function scene:destroyScene( event )     screenGroup = self.view     myImage = nil end 

Thanks for writing back as I forgot to mention this.

The problem is that these files (loaded by storyboard) are basically modules and they stay in memory forever unless you remove them.  So, all file level local variables retain handles till cleared (nil’d).

Oh, and Rob is absolutely right.  There is always the danger of name conflicts when you attach your own fields to objects created by Corona.  

The problem I often run into with giving advice is I know about the side-effects but forget to warn folks.  i.e. Sometimes I make new (more mysterious) problems for folks.

-Ed

Thanks Ed! That’s a great point which I did not know (i hate it that i did not move to Storyboard a long time ago so I did not have these feeling of not knowing what I am doing :frowning:

So If I understand you correctly, everytime I add a local variables in the “main chunk” (top the file before createScene) then I need to nil it in the destroyScene()? That’s should not be a problem but it sucks a little since I am used to not worry about any locals before (Director)

In any event thanks a lot for thinking about this issue and letting me know.

Mo

To qualify what Ed is talking about.  The texture memory associated with myImage will be cleaned up and garbage collected when the scene is disposed of (purgeScene(), purgeAll(), etc.).  What isn’t clearned up is a small amount of “Lua” memory.  The table that held all the information about that image is still in memory.  The texture memory was freed when the scene’s view (display group) is removed.

If you do a storyboard.removeScene() instead of storyboard.purgeScene() to clean up scenes you don’t use, then those main chunk locals will get cleaned up.  This isn’t a technically a memory leak in particular if you’re going to come back to this scene later.  It won’t use any more memory.  But if you are being frugal (which is a good thing!), you should clear any local tables in the destroyScene, if you’re only going to be purging, not removing.

Thanks Rob! Mo

Hi,

I am also new to storyboard (coming from Director) and also struggling on the same issue. In your case, I think you can use local myImage at the top of the module (before create) and it should accessible from both createScene() an enterScene()

Again, i am new to this so please take my suggestion with a grain of salt :slight_smile:

Hope this help.

Mo

Hey guys.  There are two ways to solve this:

1. Use file level locals (GOOD):

local storyboard = require( "storyboard" ) local scene = storyboard.newScene() local myImage -- Now visibile to createScene() and enterScene()  function scene:createScene( event )        local sceneGroup = self.view    myImage = display.newImage( sceneGroup, "image.png" ) end function scene:enterScene( event )    local sceneGroup = self.view    transition.to( myImage, { timer =1000, x =10 } )  end     

2. Use the group that storyboard gives you and attach a ‘variable collector’.  This will be visible in all ** of this scene’s **** functions, and will be automatically removed when  storyboard  destroys the scene (BETTER in many cases).**

local storyboard = require( "storyboard" ) local scene = storyboard.newScene() function scene:createScene( event )    local sceneGroup = self.view    local myData = {}    sceneGroup.data = myData    myData.myImage = display.newImage( sceneGroup, "image.png") end function scene:enterScene( event )    local sceneGroup = self.view    local myData = sceneGroup.data    transition.to(myData.myImage, { timer =1000, x =10 } )  end   

[hr]

Note: I also made some corrections to the original code:

  1. You created a newImage(), but did not insert it into sceneGroup.  If you don’t do this, that scene and storyboard will not manage it for you.  It gets placed in the top-level group by default and will not be removed or hidden if the scene changes.

  2. In one scene: callback, you called the group ‘sceneGroup’ and in the other you called it ‘scene’.

   2a. Calling it scene was wrong as that is the name you’re using for your local ‘scene’ as created/provided by storyboard.

  2b. Whatever you call the variable ‘event.view’ when you place it in a local, always use the same name in your callbacks or it will be very confusing later.

@roaminggamer

@LairdGames

PERFECT!!! your answers are absolutely appreciated! thankx guyz! :)) especially roaminggamer… suggestion #2 is somehow new and id like to try it! thnx a bunch! :))

Ed’s #1 is the best method if the variables you need are to be used only within that scene.  It is the proper way to scope your variables for use.

Ed’s #2 works if you need to pass data between scenes, though as we talked about here:

http://www.coronalabs.com/blog/2013/05/28/tutorial-goodbye-globals/

adding things to the storyboard table might be safe today, but there is no promise that we won’t add features in the future that might use the name you choose (myData is probably pretty safe, but…)   The blog post above, shows how to create a data module that you can include in each scene (or other module) that makes data available between scenes in a future safe, non-global way. 

No problem!

@roaminggamer: Thanks for the option 2! I was wondering about option 1: 

local myImage – Now visibile to createScene() and enterScene()

No p I will assume that myImage will be garbage collected when the scene is removed? For option 2 it seems that you need to preface each variable with the mydata (dot notation) but it really look good to use. Would you put all the variables you need into mydata in CreateScene() then use them in the enterScene()?

Thanks again.

Mo

EDIT: Thanks Rob for the clarification. It is very helpful. Yes I already the technique you show on that link (great stuff by the way) So I think I will use option 1 (locals variables in the main chunk) when I only need to use those variables in the same scene.

@Mo,

Hi.  The only problem  with solution #1 is that if you do not explicity clear ‘myImage’ (i.e. set to nil)in destroyScene, LUA will not garbage collect it till the module is removed from memory, which may never happen.

function scene:destroyScene( event )     screenGroup = self.view     myImage = nil end 

Thanks for writing back as I forgot to mention this.

The problem is that these files (loaded by storyboard) are basically modules and they stay in memory forever unless you remove them.  So, all file level local variables retain handles till cleared (nil’d).

Oh, and Rob is absolutely right.  There is always the danger of name conflicts when you attach your own fields to objects created by Corona.  

The problem I often run into with giving advice is I know about the side-effects but forget to warn folks.  i.e. Sometimes I make new (more mysterious) problems for folks.

-Ed

Thanks Ed! That’s a great point which I did not know (i hate it that i did not move to Storyboard a long time ago so I did not have these feeling of not knowing what I am doing :frowning:

So If I understand you correctly, everytime I add a local variables in the “main chunk” (top the file before createScene) then I need to nil it in the destroyScene()? That’s should not be a problem but it sucks a little since I am used to not worry about any locals before (Director)

In any event thanks a lot for thinking about this issue and letting me know.

Mo

To qualify what Ed is talking about.  The texture memory associated with myImage will be cleaned up and garbage collected when the scene is disposed of (purgeScene(), purgeAll(), etc.).  What isn’t clearned up is a small amount of “Lua” memory.  The table that held all the information about that image is still in memory.  The texture memory was freed when the scene’s view (display group) is removed.

If you do a storyboard.removeScene() instead of storyboard.purgeScene() to clean up scenes you don’t use, then those main chunk locals will get cleaned up.  This isn’t a technically a memory leak in particular if you’re going to come back to this scene later.  It won’t use any more memory.  But if you are being frugal (which is a good thing!), you should clear any local tables in the destroyScene, if you’re only going to be purging, not removing.

Thanks Rob! Mo