The solution where you substitute the global display.newGroup() with the patched-one may not work always.
In many libraries you see the pattern:
[lua]local newGroup = display.newGroup[/lua]
(I just used newGroup here to make the point)
Some even recommend this pattern as a best practice because it forces you to localize all the symbols that you use in your module. Leaking globals that pollute and overwrite the Lua namespace is a nasty problem.
If you use this localization, however, then it depends on when you do the patching and when do you require the module.
For example, take the following file “monkey.lua”:
[lua]local newGroup = display.newGroup
print(“monkey.newGroup begin:”, newGroup)
local monkey = {}
monkey.newGroup = function(…)
print(“monkey.newGroup:”, newGroup)
return newGroup(…)
end
return monkey[/lua]
and add a require(“monkey”) before the newGroup-patch, and substitute the first display.newGroup in the event handler with monkey.newGroup:
[lua]local monkey = require(“monkey”)
local oldNewGroup = display.newGroup
print(“oldNewGroup:”, oldNewGroup)
display.newGroup = function( … )
local group = oldNewGroup( … )
local oldRemoveSelf = group.removeSelf
group.removeSelf = function( self )
for i = self.numChildren, 1, -1 do
self[i]:removeSelf()
end
if(self.name==“ui”)then print(“newRemoveSelf”, self) end
oldRemoveSelf( self )
end
group.remove = function( self, o )
if type( o ) == ‘number’ then
self[o]:removeSelf()
else
o:removeSelf()
end
end
return group
end
–]]
– patch stage object to proxy stage:remove( o ) to o:removeSelf()
display.getCurrentStage().remove = function( self, o )
if type( o ) == ‘number’ then
self[o]:removeSelf()
else
o:removeSelf()
end
end
print(“new newGroup:”, display.newGroup)
local NamedObjects = require(“NamedObjects”)
Runtime:addEventListener(‘enterFrame’, function()
print(“new newGroup:”, display.newGroup)
NamedObjects.newGroupRef()
local g0 = monkey.newGroup()
local g1 = display.newGroup(); g0:insert(g1)
local g2 = display.newGroup(); g0:insert(g2)
local g3 = display.newGroup(); g0:insert(g3)
local r1 = display.newRect( 10, 10, 25, 25 ); g1:insert(r1)
local r2 = display.newRect( 20, 20, 25, 25 ); g1:insert(r2)
local r3 = display.newRect( 30, 30, 25, 25 ); g1:insert(r3)
local r4 = display.newRect( 40, 40, 25, 25 ); g2:insert(r4)
local r5 = display.newRect( 50, 50, 25, 25 ); g2:insert(r5)
local r6 = display.newRect( 60, 60, 25, 25 ); g2:insert(r6)
local r7 = display.newRect( 70, 70, 25, 25 ); g3:insert(r7)
local r8 = display.newRect( 80, 80, 25, 25 ); g3:insert(r8)
local r9 = display.newRect( 90, 90, 25, 25 ); g3:insert(r9)
– clear all
local stage = display.getCurrentStage()
for i = stage.numChildren, 1, -1 do
stage:remove(i)
end
– watch for leaks
collectgarbage()
print(collectgarbage(‘count’))
end)[/lua]
You will see the memory leak clearly happening on the console. If you move the require call past the patch code, all is good again.
In other words, the newGroup-patch may work most of the time and probably every time if you can ensure that the patch gets applied before any other module is loaded.
For me, the only real, fool-proof solution is if Ansca would hard-code the recursive removeSelf. Personally I cannot think of any use cases where you would want to hold on to display objects after the group they were in was deleted… and even if you have those cases where people want that, they should be forced to move their objects out of that group and put them in another before the group is removed.
Ansca are you listening?
Would appreciate your take on this…
-FrankS.
[import]uid: 8093 topic_id: 7489 reply_id: 26781[/import]