Finalize events not dispatching on children when group is dispatched ?

I’m hoping that Rob or somebody else at Corona Labs can answer this question for me: I have recently fallen absolutely in love with the finalize API, as a way of running clean-up code on display objects when they are removed. And it works great if I call display.remove() or removeSelf() on an object with a finalize listener attached. However, if an object is removed from the stage by removing it’s parent group, or by removing a Composer scene that it belongs to (which is essentially the same thing), the finalize event is not dispatched. Is this a bug, or is it this way by design?

If possible, I think it’d be an improvement if finalize events were dispatched by all the children in a display group or container when that group/container is removed. Or maybe there’s something I’m missing and it’s possible to achieve this now. Either way, any guidance would be most appreciated.

Thanks!

What version are you running?

Can you file a bug report?

Rob

Hi Rob - thanks for responding so quickly. I am running the latest daily build (2014.2358), but can also confirm this bug exists in the latest public build (2014.2189). I have filed a bug report with case # 33900. Here is the main.lua that I attached to that bug report that illustrates the bug clearly in the simulator (or on device):

------------------------------------------------------------------------------------ -- SCREEN POSITION VARIABLES ------------------------------------------------------------------------------------ local centerX = display.contentCenterX local centerY = display.contentCenterY local screenTop = display.screenOriginY local screenLeft = display.screenOriginX local screenBottom = display.screenOriginY + (display.contentHeight - (display.screenOriginY \* 2)) local screenRight = display.screenOriginX + (display.contentWidth - (display.screenOriginX \* 2)) local screenWidth = screenRight - screenLeft local screenHeight = screenBottom - screenTop ------------------------------------------------------------------------------------ -- FUNCTION TO CREATE A NEW SAMPLE OBJECT/GROUP: ------------------------------------------------------------------------------------ local function newSample() local group = display.newGroup() group.x, group.y = centerX, centerY local r, g, b = math.random(0,70)\*.01, math.random(0,70)\*.01, math.random(0,70)\*.01 local r2, g2, b2 = math.abs(r-1), math.abs(g-1), math.abs(b-1) local bg = display.newRect(group, 0, 0, screenWidth, screenHeight) bg:setFillColor(r,g,b) local object = display.newCircle(group, 0, 0, screenWidth\*.25) object:setFillColor(r2,g2,b2) local function startOver() display.remove(group) group = nil newSample() return true end local function removeObject() display.remove(object) object = nil return true end function object:finalize(event) print("Finalize Event Dispatched!") native.showAlert("Finalize Event Dispatched", "If you are seeing this alert, it means that a 'finalize' event was dispatched when the circle was removed from the stage.", {"OK"}, startOver) end object:addEventListener("finalize") object:addEventListener("tap", removeObject) bg:addEventListener("tap", startOver) local label = display.newText({ parent = group, text = "Tap the circle to call display.remove() on the circle. Tap the background to call display.remove() on the circle's parent display group (a new display group will be created immediately after). If the circle dispatches a 'finalize' event, a system alert will pop up.", x = 0, y = screenHeight\*.5, width = screenWidth - 20, height = 0, font = native.systemFont, fontSize = screenWidth\*.04, align = "center" }) label.anchorY = 1 end ------------------------------------------------------------------------------------ -- CREATE FIRST SAMPLE: ------------------------------------------------------------------------------------ newSample()

Just bumping this post in the hopes of getting an update. I haven’t heard any response to my bug report, and there doesn’t seem to be a way to check the status of a bug (or maybe I’ve missed it). Any word from the engineers, Rob?

Thanks as always!

It’s still in the queue to be worked on.

Rob

Till this is fixed in Corona, use Sergey’s fix:

https://gist.github.com/Lerg/8791421

Execute this code before creating any scenes or loading composer for the first time and you should be golden:

-- Fix problem that finalize event is not called for children objects when group is removed local function finalize(g) for i = 1, g.numChildren do if g[i].\_tableListeners and g[i].\_tableListeners.finalize then for j = 1, #g[i].\_tableListeners.finalize do g[i].\_tableListeners.finalize[j]:dispatchEvent{name = 'finalize', target = g[i]} end end if g[i].\_functionListeners and g[i].\_functionListeners.finalize then for j = 1, #g[i].\_functionListeners.finalize do g[i].\_functionListeners.finalize[j]({name = 'finalize', target = g[i]}) end end if g[i].insert then finalize(g[i]) end end end local newGroup = display.newGroup function display.newGroup() local g = newGroup() local removeSelf = g.removeSelf g.removeSelf = function() finalize(g) removeSelf(g) end return g end

Nice work around…

Rob

Sergey is a pretty smart coder.

Thanks for sharing! I knew Sergey was good, but wasn’t aware of this particular little gem…

Oh, it got updated.

Please use this version, it’s more robust:

[lua]

– Fix problem that finalize event is not called for children objects when group is removed

local function finalize(event)

    local g = event.target

    for i = 1, g.numChildren do

        if g[i]._tableListeners and g[i]._tableListeners.finalize then

            for j = 1, #g[i]._tableListeners.finalize do

                g[i]._tableListeners.finalize[j]:dispatchEvent{name = ‘finalize’, target = g[i]}

            end

        end

        if g[i]._functionListeners and g[i]._functionListeners.finalize then

            for j = 1, #g[i]._functionListeners.finalize do

                g[i]._functionListeners.finalize[j]({name = ‘finalize’, target = g[i]})

            end

        end

        if g[i].numChildren then

            finalize{target = g[i]}

        end

    end

end

local newGroup = display.newGroup

function display.newGroup()

    local g = newGroup()

    g:addEventListener(‘finalize’, finalize)

    return g

end

[/lua]

Rob, my initial bug report is “Case 30028”.

What version are you running?

Can you file a bug report?

Rob

Hi Rob - thanks for responding so quickly. I am running the latest daily build (2014.2358), but can also confirm this bug exists in the latest public build (2014.2189). I have filed a bug report with case # 33900. Here is the main.lua that I attached to that bug report that illustrates the bug clearly in the simulator (or on device):

------------------------------------------------------------------------------------ -- SCREEN POSITION VARIABLES ------------------------------------------------------------------------------------ local centerX = display.contentCenterX local centerY = display.contentCenterY local screenTop = display.screenOriginY local screenLeft = display.screenOriginX local screenBottom = display.screenOriginY + (display.contentHeight - (display.screenOriginY \* 2)) local screenRight = display.screenOriginX + (display.contentWidth - (display.screenOriginX \* 2)) local screenWidth = screenRight - screenLeft local screenHeight = screenBottom - screenTop ------------------------------------------------------------------------------------ -- FUNCTION TO CREATE A NEW SAMPLE OBJECT/GROUP: ------------------------------------------------------------------------------------ local function newSample() local group = display.newGroup() group.x, group.y = centerX, centerY local r, g, b = math.random(0,70)\*.01, math.random(0,70)\*.01, math.random(0,70)\*.01 local r2, g2, b2 = math.abs(r-1), math.abs(g-1), math.abs(b-1) local bg = display.newRect(group, 0, 0, screenWidth, screenHeight) bg:setFillColor(r,g,b) local object = display.newCircle(group, 0, 0, screenWidth\*.25) object:setFillColor(r2,g2,b2) local function startOver() display.remove(group) group = nil newSample() return true end local function removeObject() display.remove(object) object = nil return true end function object:finalize(event) print("Finalize Event Dispatched!") native.showAlert("Finalize Event Dispatched", "If you are seeing this alert, it means that a 'finalize' event was dispatched when the circle was removed from the stage.", {"OK"}, startOver) end object:addEventListener("finalize") object:addEventListener("tap", removeObject) bg:addEventListener("tap", startOver) local label = display.newText({ parent = group, text = "Tap the circle to call display.remove() on the circle. Tap the background to call display.remove() on the circle's parent display group (a new display group will be created immediately after). If the circle dispatches a 'finalize' event, a system alert will pop up.", x = 0, y = screenHeight\*.5, width = screenWidth - 20, height = 0, font = native.systemFont, fontSize = screenWidth\*.04, align = "center" }) label.anchorY = 1 end ------------------------------------------------------------------------------------ -- CREATE FIRST SAMPLE: ------------------------------------------------------------------------------------ newSample()

Hi Rob,

Just a friendly bump on this post to see if there’s any sort of ETA on having this bug fixed.

To shed some light on why I’m so antsy about it: I’ve put together what I think is a nice little module to share with the community that adds an endless “looping” scrollView with one line of code. But since it utilizes a Runtime listener, I don’t want to release it until this bug is fixed, so that I don’t need to make people go through the extra step of manually removing the looping scrollView object when they destroy the scrollView’s parent/scene (I remove the Runtime listener in the scrollView’s finalize event listener). Not the biggest biggie, I know, but just thought I’d check in.

Thanks as always!

It’s still in the queue to be worked on.

Rob

Just bumping this post in the hopes of getting an update. I haven’t heard any response to my bug report, and there doesn’t seem to be a way to check the status of a bug (or maybe I’ve missed it). Any word from the engineers, Rob?

Thanks as always!

It’s still in the queue to be worked on.

Rob

Till this is fixed in Corona, use Sergey’s fix:

https://gist.github.com/Lerg/8791421

Execute this code before creating any scenes or loading composer for the first time and you should be golden:

-- Fix problem that finalize event is not called for children objects when group is removed local function finalize(g) for i = 1, g.numChildren do if g[i].\_tableListeners and g[i].\_tableListeners.finalize then for j = 1, #g[i].\_tableListeners.finalize do g[i].\_tableListeners.finalize[j]:dispatchEvent{name = 'finalize', target = g[i]} end end if g[i].\_functionListeners and g[i].\_functionListeners.finalize then for j = 1, #g[i].\_functionListeners.finalize do g[i].\_functionListeners.finalize[j]({name = 'finalize', target = g[i]}) end end if g[i].insert then finalize(g[i]) end end end local newGroup = display.newGroup function display.newGroup() local g = newGroup() local removeSelf = g.removeSelf g.removeSelf = function() finalize(g) removeSelf(g) end return g end

Nice work around…

Rob

Sergey is a pretty smart coder.