Using native.newTextField() with Storyboard

With my current app I need to use a lot of text fields but not sure how to handle them when moving between scenes.

At the moment am making them local to the scene (at the top of the lua file, so all can access them). I then remove them in exitScene but then if I go back to that scene, they are gone (obviously) and I get errors.

So just wondering what other people do to handle text fields ?

The obvious thing to do is remove the scene from memory when it is exited, but where do I put that. Can I put it in exitScene ?

Dave

The top of the scene executes exactly once – ever, unless you un-require the file (or storyboard.removeScene… not purgeScene).  The proper place to create the text fields is in enterScene().  That way, there will always be an enterScene() and exitScene() pair and things will be managed properly.

I need to access them else where though. When the submit button is pressed on the scene I need to access the contents of the fields for instance.

If I don’t make them local at the top but put them in enterScene without the local then won’t that make them global variables ?

Dave

You can declare the variable at the top of the scene, just don’t create it until enterScene()

[lua]

   local myTextField

   local someOtherFunction()

         print(myTextField.text)

   end

   function scene:enterScene(event)

          myTextField = native.newTextField(…)

   end

   return scene

[/lua]

Maybe am misunderstanding but if I then remove them in exitScene and then goto that same scene, won’t the variables be gone (as I removed them) so be created as global variables in enterScene ? Dave

The top of the scene executes exactly once – ever, unless you un-require the file (or storyboard.removeScene… not purgeScene).  The proper place to create the text fields is in enterScene().  That way, there will always be an enterScene() and exitScene() pair and things will be managed properly.

I need to access them else where though. When the submit button is pressed on the scene I need to access the contents of the fields for instance.

If I don’t make them local at the top but put them in enterScene without the local then won’t that make them global variables ?

Dave

Hi,

What I do with textfields is declare a forward reference to them at the top of my file, this way you can access there properties from anywhere.  I generally include the code for the storyboard in the enter scene event, and remove them in exitScene.  

When the textField is submitted (or the scene changes) I put the values into a storyboard variable (persists between scenes and not global) - something like “storyboard.description = event.text” and then in the enterScene event when the textField is being recreated I reread these variables back into the textField “textBox.text = storyboard.description”.

Hope this helps,

Craig

How do you remove them exitScene ?

My point is if they are removed in exitScene, then you call the scene again, they will be created in enterScene and hence will be Global not local to that scene.

Although you have created them at the top first time, if you then remove them in exitScene, they are gone. The code at the top is never run again unless the scene is removed from memory.

Dave

Here is a copy of some code i am using,  hope this helps…  I am using storyboard variables (kind of global(ish)) to keep the value of the textfield.

[lua]local storyboard = require( “storyboard” )
local scene = storyboard.newScene()
local widget = require “widget”
local textField  – Forward Reference to the

– Called when the scene’s view does not exist:
function scene:createScene( event )
        local group = self.view
 local myButton = widget.newButton  – button created in before scene moves into view
  {
      left = 100,
      top = 200,
      width = 150,
      height = 50,
      id = “button_1”,
      label = “Button”,
      onRelease = function(event)
       storyboard.description = textField.text  – store the value of textfield for later use
    storyboard.gotoScene(“storyboard2”, {effect = “slideRight”, time = 600});
      end,
  }
  group:insert(myButton)

end

– Called immediately after scene has moved onscreen:
function scene:enterScene( event )
        local group = self.view
  local function inputListener( event )  – handler for text field
      if event.phase == “began” then
 
          – user begins editing textField
          print( event.text )
 
      elseif event.phase == “ended” then
    storyboard.description = event.text
          – do something with textField’s text
 
      elseif event.phase == “editing” then

      end
  end
 
  textField = native.newTextField( 20, 60, display.contentWidth - 40, 40 )  –  create the textfield once it has moved on stage
  textField.text = storyboard.description  – get the stored value
  native.setKeyboardFocus( textField )
  textField.font = native.newFont( “Helvetica-Light”, 18 )
  textField:addEventListener( “userInput”, inputListener )

end

– Called when scene is about to move offscreen:
function scene:exitScene( event )
        local group = self.view
  textField:removeSelf()
end

– Called prior to the removal of scene’s “view” (display group)
function scene:destroyScene( event )
        local group = self.view

end

– END OF YOUR IMPLEMENTATION

– “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[/lua]

Thanks for that, that is very simular to how I am doing it at the moment (am not saving the state in a storyboard var though).

My problem is because you have used removeSelf() in the exitScene when you go back to enterScene that variable no longer exists (because you removed it) and you then create it in enterScene, hence I then think that text field is then global.

It’s probably fine but always read to never have global variables if you can help it. My problem is, my app is a business app so I have a lot of text fields and hence a lot of global text fields until that scene is exited.

Dave

The variable still exits. It is nil, which means it contains nothing. When you re-create the text field and assign it to the exiting variable, you are still local, not global.

You can declare the variable at the top of the scene, just don’t create it until enterScene()

[lua]

   local myTextField

   local someOtherFunction()

         print(myTextField.text)

   end

   function scene:enterScene(event)

          myTextField = native.newTextField(…)

   end

   return scene

[/lua]

I thought nil variables would be garbage collected. So if I use removeSelf it doesn’t actually remove it ? Or are you saying use removeSelf but don’t set it to nil ? Dave

Maybe am misunderstanding but if I then remove them in exitScene and then goto that same scene, won’t the variables be gone (as I removed them) so be created as global variables in enterScene ? Dave

Variables are just boxes that old a very small amount of data (4 bytes in most cases).  If it’s something bigger like a function or a table/object, the variable just holds a pointer to the larger allocated chunk of memory.  When you create an object, like a native.newTextField and stick it in a variable called myField, then what myField really contains is a number, generally printed in hexadecimal like:

0x493ba832

That is the memory address of where that native.newTextField object really exists. When you do a :removeSelf() on the object, that allocated memory is marked as being free and when you do:

myField = nil

you are erasing the memory pointer, setting myField back to nothing.  However, your code still knows about myField.  It knows it’s a variable that can contain something, so if you re-use it, it’s using the same name just next time it’s contents are different.

Maybe this analogy will help:  You have a coffee pot you want to give a way.  You put it in a box and sit it on the street.  Thats the :removeSelf().  Now you put a sign on the box saying “Free to a good home”.  That’s setting the variable to nil.  When someone comes and takes the coffee pot, that’s the garbage collector taking the data away and you’re left with an empty box – your variable.

Hi,

What I do with textfields is declare a forward reference to them at the top of my file, this way you can access there properties from anywhere.  I generally include the code for the storyboard in the enter scene event, and remove them in exitScene.  

When the textField is submitted (or the scene changes) I put the values into a storyboard variable (persists between scenes and not global) - something like “storyboard.description = event.text” and then in the enterScene event when the textField is being recreated I reread these variables back into the textField “textBox.text = storyboard.description”.

Hope this helps,

Craig

How do you remove them exitScene ?

My point is if they are removed in exitScene, then you call the scene again, they will be created in enterScene and hence will be Global not local to that scene.

Although you have created them at the top first time, if you then remove them in exitScene, they are gone. The code at the top is never run again unless the scene is removed from memory.

Dave

Here is a copy of some code i am using,  hope this helps…  I am using storyboard variables (kind of global(ish)) to keep the value of the textfield.

[lua]local storyboard = require( “storyboard” )
local scene = storyboard.newScene()
local widget = require “widget”
local textField  – Forward Reference to the

– Called when the scene’s view does not exist:
function scene:createScene( event )
        local group = self.view
 local myButton = widget.newButton  – button created in before scene moves into view
  {
      left = 100,
      top = 200,
      width = 150,
      height = 50,
      id = “button_1”,
      label = “Button”,
      onRelease = function(event)
       storyboard.description = textField.text  – store the value of textfield for later use
    storyboard.gotoScene(“storyboard2”, {effect = “slideRight”, time = 600});
      end,
  }
  group:insert(myButton)

end

– Called immediately after scene has moved onscreen:
function scene:enterScene( event )
        local group = self.view
  local function inputListener( event )  – handler for text field
      if event.phase == “began” then
 
          – user begins editing textField
          print( event.text )
 
      elseif event.phase == “ended” then
    storyboard.description = event.text
          – do something with textField’s text
 
      elseif event.phase == “editing” then

      end
  end
 
  textField = native.newTextField( 20, 60, display.contentWidth - 40, 40 )  –  create the textfield once it has moved on stage
  textField.text = storyboard.description  – get the stored value
  native.setKeyboardFocus( textField )
  textField.font = native.newFont( “Helvetica-Light”, 18 )
  textField:addEventListener( “userInput”, inputListener )

end

– Called when scene is about to move offscreen:
function scene:exitScene( event )
        local group = self.view
  textField:removeSelf()
end

– Called prior to the removal of scene’s “view” (display group)
function scene:destroyScene( event )
        local group = self.view

end

– END OF YOUR IMPLEMENTATION

– “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[/lua]

Thanks for that, that is very simular to how I am doing it at the moment (am not saving the state in a storyboard var though).

My problem is because you have used removeSelf() in the exitScene when you go back to enterScene that variable no longer exists (because you removed it) and you then create it in enterScene, hence I then think that text field is then global.

It’s probably fine but always read to never have global variables if you can help it. My problem is, my app is a business app so I have a lot of text fields and hence a lot of global text fields until that scene is exited.

Dave