Listeners and Storyboard

I am building my first app and I’m having a hard time combining 2 of your basic tutorials. I simply want to have a button that will move from one scene to another. I created a Storyboard template, then from main.lua I call storyboard.gotoScene( "welcomeScreen" ) which works fine. From then on, on welcomeScreen.lua, I am trying to use the basic example of creating a button and adding a eventListener to it but I get the error message below. Since the Storyboard template is so basic, I can’t seem to understand what’s the issue here.

Here’s the error:
[text]
Runtime error
…ropbox/Projects/Corona/SpellingApp/welcomeScreen.lua:51: attempt to index local ‘wordSearchButton’ (a nil value)
stack traceback:
[C]: ?
…ropbox/Projects/Corona/SpellingApp/welcomeScreen.lua:51: in main chunk
[C]: in function ‘require’
?: in function ‘gotoScene’
…/rafael/Dropbox/Projects/Corona/SpellingApp/main.lua:12: in main chunk
Runtime error: …ropbox/Projects/Corona/SpellingApp/welcomeScreen.lua:51: attempt to index local ‘wordSearchButton’ (a nil value)
stack traceback:
[C]: ?
…ropbox/Projects/Corona/SpellingApp/welcomeScreen.lua:51: in main chunk
[C]: in function ‘require’
?: in function ‘gotoScene’
…/rafael/Dropbox/Projects/Corona/SpellingApp/main.lua:12: in main chunk
[/text]
And here’s the code for welcomeScreen.lua:

-----------------------------------------------------------------------------------------  
--  
-- welcomeScreen.lua  
-- by Rafael Gaino on March 7th, 2012  
-----------------------------------------------------------------------------------------  
  
local storyboard = require( "storyboard" )  
local scene = storyboard.newScene()  
  
--------------------------------------------  
local wordSearchButton  
  
-----------------------------------------------------------------------------------------  
-- BEGINNING OF YOUR IMPLEMENTATION  
--   
-- NOTE: Code outside of listener functions (below) will only be executed once,  
-- unless storyboard.removeScene() is called.  
--   
-----------------------------------------------------------------------------------------  
  
-- Called when the scene's view does not exist:  
function scene:createScene( event )  
  
 local screenGroup = self.view  
  
 wordSearchButton = display.newImage( "images/buttons/WordSearchButton.png" )  
 wordSearchButton.x = 150  
 wordSearchButton.y = display.contentHeight/2  
 screenGroup:insert( wordSearchButton )  
  
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 )  
end  
  
-- If scene's view is removed, scene:destroyScene() will be called just prior to:  
function scene:destroyScene( event )  
end  
  
-- Listeners  
function wordSearchButton:tap( event )  
 print("wordSearchButton tapped")  
end  
  
wordSearchButton:addEventListener( "tap", wordSearchButton )  
  
-----------------------------------------------------------------------------------------  
-- 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 whenever 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  

[import]uid: 41579 topic_id: 22970 reply_id: 322970[/import]

Ok, I think I figured out that this was a scope issue. By declaring wordSearchButton immediately as a display.newImage() I managed to make the call to addEventListener successfull. I’m still not confident that this is the best way to do what I’m trying to achieve here. Can anyone chime in please?

Thank you. Here’s the running version of my welcomeScreen.lua:

[code]
local storyboard = require( “storyboard” )
local scene = storyboard.newScene()


local wordSearchButton = display.newImage( “images/buttons/WordSearchButton.png” )


– BEGINNING OF YOUR IMPLEMENTATION

– NOTE: Code outside of listener functions (below) will only be executed once,
– unless storyboard.removeScene() is called.


– Called when the scene’s view does not exist:
function scene:createScene( event )

local screenGroup = self.view

–wordSearchButton = display.newImage( “images/buttons/WordSearchButton.png” )
wordSearchButton.x = 150
wordSearchButton.y = display.contentHeight/2
screenGroup:insert( wordSearchButton )
wordSearchButton:addEventListener( “tap”, wordSearchButton )

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 )
end

– If scene’s view is removed, scene:destroyScene() will be called just prior to:
function scene:destroyScene( event )
end

– Listeners
function wordSearchButton:tap( event )
print(“wordSearchButton tapped”)
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 whenever 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
[/code] [import]uid: 41579 topic_id: 22970 reply_id: 91751[/import]

Your first attempt is more correct but has some errors. You need to create all display objects in “createScene”. You need to add listener to an object in “enterScene”. And you need to define you function before you call it or make a forward referens. So it looks like this

[code]


– welcomeScreen.lua
– by Rafael Gaino on March 7th, 2012

local storyboard = require( “storyboard” )
local scene = storyboard.newScene()


local wordSearchButton


– BEGINNING OF YOUR IMPLEMENTATION

– NOTE: Code outside of listener functions (below) will only be executed once,
– unless storyboard.removeScene() is called.


– Listeners
local function wordSearchButtonTap( event )
print(“wordSearchButton tapped”)
end

– Called when the scene’s view does not exist:
function scene:createScene( event )

local screenGroup = self.view

wordSearchButton = display.newImage( “images/buttons/WordSearchButton.png” )
wordSearchButton.x = 150
wordSearchButton.y = display.contentHeight/2
screenGroup:insert( wordSearchButton )

end

– Called immediately after scene has moved onscreen:
function scene:enterScene( event )
wordSearchButton:addEventListener( “tap”, wordSearchButtonTap )
end

– Called when scene is about to move offscreen:
function scene:exitScene( event )
end

– If scene’s view is removed, scene:destroyScene() will be called just prior to:
function scene:destroyScene( event )
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 whenever 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
[/code] [import]uid: 40334 topic_id: 22970 reply_id: 91773[/import]

Great, thanks. Do I need to do any cleanup on this case? Should I remove the listeners exitScene? [import]uid: 41579 topic_id: 22970 reply_id: 91790[/import]

@rgaino

Did you figure out if you need to remove listeners when you change scene? I have the same question…

daf [import]uid: 58825 topic_id: 22970 reply_id: 91983[/import]

@dafwilli

No, I didn’t. I would think so because enterScene and exitScene are equivalents. This way listeners are not active when the scene is not active. [import]uid: 41579 topic_id: 22970 reply_id: 91995[/import]

In this case no clean-up is necessary, because the listener is attached to a display object and storyboard take care of display objects. But if you would register a runtime listener or a timer or a transition, in that case you need to clean those up in “exitScene”. [import]uid: 40334 topic_id: 22970 reply_id: 92000[/import]