Removing an RuntimeEventListener from an 'object'

Hello Everyone,

I’ve been dealing with an issue while working with the RuntimeEventListener. I’ve got class that has it’s own ‘touch’ function. I’ve been able to successfully hook up the touch function to the RuntimeEventListener, but I’m having no luck actually removing the event! So once I move into another state the touch function is still running! Even after I destroy the object! Is there something I’m missing here?

[lua] – Psuedo-code Example of the class I’ve created
function class:new(o)
– initialize object via weak table
end

function class:touch(event)
– some code
end[/lua]

[lua]-- How I add the event
Runtime:addEventListener(“touch”, self)[/lua]

[lua]-- How i’m trying to remove the event
function class:destroy()
Runtime:removeEventListener(“touch”, self)
self = nil
end[/lua] [import]uid: 99450 topic_id: 26381 reply_id: 326381[/import]

Usually touch events are not added to the Runtime. Usually they are just added to the object specifically. [import]uid: 10903 topic_id: 26381 reply_id: 106970[/import]

Are you sure destroy() is being called? [import]uid: 8271 topic_id: 26381 reply_id: 107004[/import]

Hi Guys,

Thank you for responding.

@crssmn: Ah. Unfortunately I need to use two pieces of data from the object itself inside the touch event. Is there another way of getting object-specific data into the touch event?

@horacebury: Yes, destroy is getting called at the appropriate time. I’ve been using print statements to verify that the function is getting called and that the object is being set to nil. The object and image seem to be successfully removed, but every instance of the ‘touch’ event remains in the Runtime. =(

[import]uid: 99450 topic_id: 26381 reply_id: 107038[/import]

You must be attaching the event more than once? [import]uid: 8271 topic_id: 26381 reply_id: 107047[/import]

Yes. Right now there is 1 ‘touch’ event being added to the RunTime for every instance of the object. On average 12 instances of the object will exist at one time.

Edit:
A thought just popped in my head. Would I be able to just add the object-specific data as 2 variables to the image and grab them when the image is called from a ‘touch’ event? Is there any reason why this data wouldn’t be sent with the touch event’s target?

[lua] – Custom Touch Event
local function mytouch(event)
local a = event.target.a
local b = event.target.b

event.target:removeEventListener(‘touch’, mytouch)
end

– Initialization
function class:new(sFoo, sBabble, o )

– Initialize ‘o’ as weak table

o.myImage = display.createImage(…)
o.myImage.a = sFoo
o.myImage.b = sBabble

o.myImage:addEventListener(‘touch’, mytouch)
end[/lua] [import]uid: 99450 topic_id: 26381 reply_id: 107050[/import]

The basics: If you want to handle the touch per object, attach the event to the object. If you want to handle the touch per world, attach it to the world. This means that you are going about it the wrong way. You need to either attach you handler only once to the world (via the RunTime object) or once to each object you place in the world.

This is what @crssmn meant.

Tutorial for handling touch events properly: http://blog.anscamobile.com/2012/04/corona-touch-events-tutorial/

Try this:
[lua]function touch(event)
print(event.name,event.phase,event.target.id)
end

for i=1, 10 do
local ball = display.newCircle(100,50*i,25)
ball.id = i
ball:addEventListener(“touch”, touch)
end[/lua]

That code uses only one event function but can distinguish between the different objects. [import]uid: 8271 topic_id: 26381 reply_id: 107064[/import]

Hey Horacebury,

Thank you, but unfortunately that approach doesn’t help me. =( I MUST be able to retrieve data from the object itself during the ‘touch’ event, or be able to pass that data to the event handler. Unless there’s another way to do this, attaching the event to the Runtime seems to be my only option right now.

Getting back to my original question, do you guys think it might have something to do with the fact that i’m registering up 12 events in the Runtime? [import]uid: 99450 topic_id: 26381 reply_id: 107166[/import]

Maybe you could clarify what you’re trying to do? Doesn’t seem clear to me.

IF you do something like:

button1.value = 1  
button2.value = 2  
button3.value = 3  
  
local function buttonlistener( event )  
if event.phase == "began" then  
print(event.target.value)  
event.target:removeEventListener( "touch", buttonlistener )  
display.remove( event.target )  
event.target = nil  
end  
end  
  
button1:addEventListener( "touch", buttonlistener )   
button2:addEventListener( "touch", buttonlistener )   
button3:addEventListener( "touch", buttonlistener )   
  

Is this what you’re looking for? [import]uid: 10903 topic_id: 26381 reply_id: 107190[/import]

It might not be obvious, but the print statement in the touch handler in my code sample does access data attached to the object which is being touched. The ‘id’ property of the object is printed out.

I think you need to read the touch event tutorial again carefully. Everything you want to do is possible and every Corona developer does it daily.

There are two objects involved in a touch event: the object being listened to for the touch action and the function called when the actual touch happens.

The object being listened to (in your case this is ‘Runtime’) comes at the start of the addEventListener statement.

The function which gets called when a touch actually happens is passed in the second parameter of the addEventListener call. In this way you can listen to any object for a touch and fire any function in response.

You must never attach more than one of the same event to the same object, because of the problem you’ve been having. You either attach it to Runtime and listen globally while responding globally or you attach specifically to the object and respond on the object.

Read the tutorial again. [import]uid: 8271 topic_id: 26381 reply_id: 107281[/import]