removeEventListener - not working as it did before?

Hi, running 749

Within the previous version I was able to remove event listener even if they where created later in the code. Is this something that has changed or could this be a bug?

This following sample (could have errors, just wrote it of my head) gives me an error of:

ERROR: nil key supplied for property lookup.

local btnPO = display.newImage("assets/btn.png",0,0)  
  
local closeMe = function()  
 btnPO:removeEventListener("touch", closeMe)  
 closeMe()  
end  
  
btnPO:addEventListener("touch",closeMe)  

Am I wrong or whats happening?

Joakim [import]uid: 81188 topic_id: 22029 reply_id: 322029[/import]

Joakim,

It looks like you have a recursive call to closeMe()

[lua]local btnPO = display.newImage(“assets/btn.png”,0,0)

local closeMe = function()
btnPO:removeEventListener(“touch”, closeMe)
– REMOVE THIS closeMe()
end

btnPO:addEventListener(“touch”,closeMe)[/lua] [import]uid: 16734 topic_id: 22029 reply_id: 87560[/import]

Sorry, I just wrote it down from my head. This is the code, and it doesn’t work…

local btnPO = display.newImage("icon.png",0,0)  
   
local monkey = function()  
 btnPO:removeEventListener("touch", monkey)  
  
end  
   
btnPO:addEventListener("touch",monkey)  
  

Stil generating the same error…and thats all the code there is in my main.lua [import]uid: 81188 topic_id: 22029 reply_id: 87565[/import]

Joakim,

Yes, this is now broken in the latest daily build. You can work around it by switching to the other style of touch listener like this:

[lua]local btnPO = display.newImage(“icon.png”,0,0)

local function monkey(self, event)
print( “event.phase=”, event.phase )
if ( event.phase == “ended” or event.phase == “cancelled” ) then
print( “removing touch listener” )
btnPO:removeEventListener(“touch”, monkey)
end
end

btnPO.touch = monkey
btnPO:addEventListener(“touch”,btnPO)[/lua]

I’ve reported this to Ansca. If I hear anything back I will update you. [import]uid: 16734 topic_id: 22029 reply_id: 87566[/import]

Thanks Ken, it has been driving me nuts a couple of days now!

Joakim [import]uid: 81188 topic_id: 22029 reply_id: 87567[/import]

Interestingly enough, you can still use either approach for “tap” events. It appears that only “touch” events are broken. [import]uid: 16734 topic_id: 22029 reply_id: 87569[/import]

Strange, well thats the curse of using daily build :slight_smile:

I prefer to use touch instead of tap, why? - I don’t know :slight_smile:

Best regards, Joakim [import]uid: 81188 topic_id: 22029 reply_id: 87571[/import]

This doesn’t appear to be a problem with touch at all. This is a problem with the style of “function” call.

If you do the minor change shown below it works fine. However, if you use the other style of function call (see below) it fails.

Personally, I have never liked the second style of function call. I think it isn’t as readable for programmers who have experience with other languages.

[lua]local btnPO1 = display.newImage(“icon.png”,0,0)
local btnPO2 = display.newImage(“icon.png”,0,128)

– This style works fine
local function monkey1(event)
btnPO1:removeEventListener(“touch”, monkey1)
print( “monkey”)
end

print( "btnPO = ", btnPO1 )
btnPO1:addEventListener(“touch”,monkey1)

– This style now fails
local monkey2=function(event)
btnPO2:removeEventListener(“touch”, monkey2)
print( “monkey”)
end

print( "btnPO = ", btnPO2 )
btnPO2:addEventListener(“touch”,monkey2)[/lua]

So the final answer is use the standard function declaration and you will be fine. [import]uid: 16734 topic_id: 22029 reply_id: 87575[/import]

I don’t think this is a bug. This is a Lua-ism about the life-cycle/scope of local functions.

There is a section dedicated to this subtle behavior in Programming in Lua:
http://www.lua.org/pil/6.2.html
As I interpret PiL, The problem with monkey2 is that in the function declaration, the local definition of monkey2 is not yet defined so Lua creates and uses a global version (which is nil). So essentially, this is what is being called in the monkey2 function:

btnPO2:removeEventListener(“touch”, nil)

If you want this to work, instead of this:

local monkey2=function(event)  

you want:

local function monkey2(event)  

or

local monkey2  
monkey2=function(event)  

(By the way, this never should have worked in earlier versions of Corona either. This is a Lua language thing which we don’t mess with.)

[import]uid: 7563 topic_id: 22029 reply_id: 87586[/import]

@ewing,

Thank you for the explanation. I never use that style so I was merely trying to find a solution for Joakim.

I’ve run into something similar in the past and either use forward references or remove the “local” from the function declaration. What confused me is when Joakim said it used to work, but no longer worked in the latest buil.d

Always nice to learn the underlying language structure.

Ken [import]uid: 16734 topic_id: 22029 reply_id: 87588[/import]

Wow ow ow. This is interesting. At the very least, I feel better about the way I set up my functions. I can’t help myself but create functions like: local function myFunction(event)

Now I feel better about the way I write my code. Hehehe.

Naomi

[import]uid: 67217 topic_id: 22029 reply_id: 87602[/import]

Well done - so it is a normal LUA behavior then but I can’t figure it out…

Below is the block of code I am trying to run, and I am using storyboard - I don’t know if this has something to do with it.

Look at line 87 and 88 - theres where I try to remove the listener. The listener is created at line 217 and 218, and the function is at 170 and 183.

-- Called when the scene's view does not exist:  
function scene:createScene( event )  
  
 -----------------------------------------------------------------------------  
  
 -- CREATE display objects and add them to 'group' here.  
 -- Example use-case: Restore 'group' from previously saved state.  
  
 -----------------------------------------------------------------------------  
  
 local group = self.view  
  
  
 require "LevelHelperLoader"  
 application.LevelHelperSettings.directorGroup = group  
 loader = LevelHelperLoader:initWithContentOfFile("safari.plhs")  
 loader:instantiateSprites()  
 local myParallax = loader:parallaxNodeWithUniqueName("parallax")  
 local myClouds = loader:parallaxNodeWithUniqueName("clouds")  
  
 local sign\_right = loader:spriteWithUniqueName("NEXT")  
 local sign\_left = loader:spriteWithUniqueName("PREV")  
 sign\_left.alpha = 0  
  
 --Get Jimmy  
 local Jimmy = loader:spriteWithUniqueName("jimmy")  
 Jimmy.alpha = 0  
  
  
 local hold = function()  
 transition.to(Jimmy,{alpha=1,time=1000})  
  
 end  
 timer.performWithDelay(4000, hold,1)  
  
  
 local function openGallery( event )  
  
 if event.phase =="began" then  
  
 display.getCurrentStage():setFocus( btnPO )   
  
  
 elseif event.phase == "ended" then  
  
 display.getCurrentStage():setFocus(nil)  
 --group.isVisible = false;   
 parentsOnly.showGallery()  
 --transition.to(group,{alpha=0,time=500})  
 return true;  
 end  
  
  
 end;  
 loader:spriteWithUniqueName("ALBUM"):addEventListener("touch",openGallery)  
  
 -- Knyt alla böcker till samma eventListener  
 --local spritesWithTag = loader:spritesWithTag(LevelHelper\_TAG.DOWNLOAD)  
 --for i = 1, #spritesWithTag do  
 -- local mySprite = spritesWithTag[i];  
 -- mySprite:alpha=1  
 --end  
  
  
 -- PO Button  
  
 -- Dummy line for alignment  
  
 --local myLine = display.newImage("assets/line.png",screenW/2-3,10);  
 --myLine:setReferencePoint( display.TopCenterReferencePoint );   
  
 local btnPO = display.newImage("assets/GUI\_POLock\_gray.png",screenW-40,10)  
 btnPO.alpha = 0   
 group:insert(btnPO)  
 transition.to(btnPO,{alpha=1,time=1000})  
  
 local function openPO( event )  
  
 if event.phase =="began" then  
  
 display.getCurrentStage():setFocus( btnPO )   
  
  
 elseif event.phase == "ended" then   
 display.getCurrentStage():setFocus(nil)  
  
 leftRect:removeEventListener("touch",prevAnimal)  
 rightRect:removeEventListener("touch",nextAnimal)  
  
 myParallax:setPaused(true)  
 myClouds:setPaused(true);  
 group.isVisible = false;   
 parentsOnly.showLock()  
  
 local tablesetup = [[UPDATE gamedata set opened = 1;]];  
 db:exec( tablesetup );  
  
 return true;  
 end  
  
  
 end;  
  
 btnPO:addEventListener("touch",openPO);  
  
  
 local function checkSigns( value )  
 if value \> 1 then  
 transition.to(sign\_left,{alpha=1,300})  
 elseif value == 1 then  
 transition.to(sign\_left,{alpha=0,300})  
 end   
  
 if value == maxAnimal then  
 transition.to(sign\_right,{alpha=0,300})  
 elseif value \> 2 then  
 transition.to(sign\_right,{alpha=1,300})  
 end  
 end  
  
  
  
 local function stepLeft()  
 local i = 0  
 --Movement control  
 local function easeIn()  
 i = i + 1;   
 myParallax.position.x = myParallax.position.x - (i\*13/2);  
 if i == 22 then  
 local function easeOut()  
 i = i - 1  
 myParallax.position.x = myParallax.position.x - (i\*13/2);   
 if(i==0) then  
 isMoving = false;  
 --print(myParallax.position.x, animal)  
 end   
 end  
 timer.performWithDelay(10, easeOut,22)  
 end   
 end  
 timer.performWithDelay(10, easeIn,22)  
 --End movement control   
  
 end  
  
 local function stepRight()  
 local i = 0;  
 -- Movemment control of Parallax  
 local function easeIn()  
 i = i + 1;   
 myParallax.position.x = myParallax.position.x + (i\*13/2);   
 if i == 22 then  
 local function easeOut()  
 i = i - 1  
 myParallax.position.x = myParallax.position.x + (i\*13/2);  
  
 if(i==0) then  
 isMoving = false;  
 end   
 end  
 timer.performWithDelay(10, easeOut,22)  
 end   
 end  
 timer.performWithDelay(10, easeIn,22)  
 --End movement controll of parallax  
  
 end  
 --local function monkey2(event)   
  
 local function nextAnimal( event )  
 if event.phase == "ended" then  
 if isMoving == false then  
 isMoving = true;  
 animal = animal + 1  
 checkSigns(animal);  
 stepLeft();  
 end  
  
 end  
  
 end  
  
 local function prevAnimal( event )  
 if event.phase=="ended" then  
 if isMoving == false then  
 isMoving = true;  
  
 animal = animal - 1  
  
 checkSigns(animal);  
  
 stepRight();  
 end   
  
 end  
 end  
  
  
 --Add eventlisteners for the buttons  
 sign\_right:addEventListener("touch",nextAnimal)  
 sign\_left:addEventListener("touch", prevAnimal)  
  
 --===================================================================  
 --Osynliga rektanglar för snabb navigering  
 --===================================================================  
  
 --Vänster rektangel  
 leftRect = display.newRect(0,0, 100, 768)  
 leftRect.alpha = 0  
 leftRect.isHitTestable = true  
  
 --Höger rektangel  
 rightRect = display.newRect(924,0, 100, 768)  
 rightRect.alpha = 0   
 rightRect.isHitTestable = true  
  
 leftRect:addEventListener("touch",prevAnimal)  
 rightRect:addEventListener("touch",nextAnimal)  
  
  
local function moveScene( event)  
  
 if(event.phase=="began") then  
 x0 = event.x  
  
 end  
 if(event.phase=="moved") then  
  
  
 if(x0-event.x\>200 or x0-event.x \< -200 and animal \> 0) then  
  
 if(x0 \< event.x) then  
 if isMoving==false and animal \> 1 then  
 animal = animal - 1  
 checkSigns(animal);  
 isMoving=true;  
 stepRight();  
 end  
 else  
 if isMoving==false and animal \< maxAnimal then  
 animal = animal + 1  
 checkSigns(animal);  
 isMoving=true;  
 stepLeft();  
 end  
 end  
 end   
  
  
 end  
  
end   
  
Runtime:addEventListener("touch", moveScene)  
  
-- Funktion från alla små fönster i PO att sätta tillbaka synligheten på spelet...  
local function reSet()  
 group.isVisible=true;  
 myParallax:setPaused(false)  
 myClouds:setPaused(false);  
  
 --transition.to(group,{alpha=1,time=100})  
end   
master.reSet = reSet;   
  
local function moveParallax(position, step)  
 myParallax.position.x = position  
 animal = step  
 checkSigns(step)  
end   
master.moveParallax = moveParallax;   
  
parentsOnly.setTarget(master);  
  
end  
  

Best regards, Joakim
[/code] [import]uid: 81188 topic_id: 22029 reply_id: 87645[/import]

So I think your problem is kind of similar to what’s described at the very bottom of that page in PiL
(http://www.lua.org/pil/6.2.html)

Your problem is that you are trying to use prevAnimal & nextAnimal on line 87,88. But you don’t actually declare/create them until later (line 170,183). Lua reads in your code from top to bottom. When you hit line 87, Lua looks for a variable called prevAnimal. Nothing has been created/declared yet. So Lua assumes you mean a global variable called prevAnimal. This global variable is different than the local variable you will later create on 183.

Put:
local prevAnimal
local nextAnimal
at the top of your code. I bet this will solve your problem.

[import]uid: 7563 topic_id: 22029 reply_id: 87647[/import]

Thanks, that cleared everything out. Makes me look a little bit stupid dohh :slight_smile:

Regards, Joakim [import]uid: 81188 topic_id: 22029 reply_id: 87651[/import]