ImageSheets : how to properly dispose them?

Hey guys,

just a quick question on disposing imageSheets on scene exit using storyboard.

When I load my scene I require the spriteSheet data, forward reference the spriteSheet and call graphics for the imageSheet in my create:scene(event).

That works fine.

Then in my exitScene(event) I dispose of it but when I call display.remove(spriteSheet) or spriteSheet:removeSelf() I get an error;

attempt to index upvalue ‘spriteSheet’ (a userdata value)…

if I just do

spriteSheet = nil

then it doesn’t trow an error, Is it enough to just nil out the reference for it to be removed from texture memory when I exit scenes?

userdata is part of memory used by C underneath Lua. If you open documentation of imageSheet you will see that there is stated that it has nither properties nor functions. Your nilling just removes reference to memory in which data for sheet resides but you cannot do anything with sheet itself. You just have to take for granted that Corona manages it and you nil all references when not needed.

So then I just nil the reference in my exitScene() and I’ll be fine. 

I noticed I had a little typo in my scene, I had written:

display:remove(obj)

instead of the correct way:

display.remove(obj)

I would assume Corona would throw an error in the terminal but it doesn’t, usually if something is not declared anywhere it would give an error?!?!?

Thanks for the help.

There is nothing you can do, only can free reference (maybe collector kicks in or maybe even nothing happens on lua level - just speculations).

It probably didn’t throw error because
[lua]
display:remove(obj)
display.remove(display, obj)
[/lua]
both lines are equal. Colon allows you to skip first argument which is group (can be any table, object or group) on which you called function.
So when you tried to use second variant corona/lua treated your ‘obj’ as first argument and second was nil (not provided). So you tried to remove nil feom ‘obj’ and remove() function probably checked for nil and didn’t even tried to perform removal (which would throw error)

Hi again,

I checked into this a bit further, and our engineers confirm that if you nil out the reference to the image sheet, Corona will clear it up from memory behind the scenes. As you noticed, an image sheet is a userdata object, so it does not fall under jurisdiction of display.remove() or object:removeSelf(). Also, since “collectgarbage()” shows only the Lua memory, it’s not a perfect representation of the memory being used when you load/unload image sheets… this is why if you test a load + unload of image sheets while running a Lua memory checker loop, the numbers may not “add up” as you expect, but the cleanup is occurring at the core level.

Hope this helps,

Brent

Thanks for clearing things up, the old sprite API had a dispose() function and while I was searching the forum I had a read thru the “[Tips] Optimization 101” thread and didn’t see anything about imageSheets so I just started wondering…

Another question…

What is best to use for static objects (backgrounds, logos, anything not animated…), newSprite() or newImageRect()???

I think that newImageRect(), becaue newSprite() is usually for animated or changing(switching) images. With newSprite() you must always define sequence data. Both methods uses imageSheet. So newImageRect() will handle both  sheets and image filename, where sprite needs sheet with animation.

When I have button which will change it looks when interacted then I create image sheet and spirte with only one sequence having all images. Then on change I use setFrame() to change look.

If I have some more similar images or images which appears a lot, then it’s smarter to pack everything into sheet (be aware sheet sizes are limited, so sometimes you have to break it into smaller sheets to fit size restrictions) and load images through newImageRect( imageSheet, frame, frameWidth, frameHeight) - this cannot be animated, you just create image from part of sheet. Thanks to that you do not have to load image each time but only once (sheet). Then you just dynamicaly take parts of this sheet to create images (so it’s a lot more efficient)

If I have backgrounds, logos etc (big or unique images) then I load them through newImageRect( filename, imageWidth, imageHeight )

userdata is part of memory used by C underneath Lua. If you open documentation of imageSheet you will see that there is stated that it has nither properties nor functions. Your nilling just removes reference to memory in which data for sheet resides but you cannot do anything with sheet itself. You just have to take for granted that Corona manages it and you nil all references when not needed.

So then I just nil the reference in my exitScene() and I’ll be fine. 

I noticed I had a little typo in my scene, I had written:

display:remove(obj)

instead of the correct way:

display.remove(obj)

I would assume Corona would throw an error in the terminal but it doesn’t, usually if something is not declared anywhere it would give an error?!?!?

Thanks for the help.

There is nothing you can do, only can free reference (maybe collector kicks in or maybe even nothing happens on lua level - just speculations).

It probably didn’t throw error because
[lua]
display:remove(obj)
display.remove(display, obj)
[/lua]
both lines are equal. Colon allows you to skip first argument which is group (can be any table, object or group) on which you called function.
So when you tried to use second variant corona/lua treated your ‘obj’ as first argument and second was nil (not provided). So you tried to remove nil feom ‘obj’ and remove() function probably checked for nil and didn’t even tried to perform removal (which would throw error)

Hi again,

I checked into this a bit further, and our engineers confirm that if you nil out the reference to the image sheet, Corona will clear it up from memory behind the scenes. As you noticed, an image sheet is a userdata object, so it does not fall under jurisdiction of display.remove() or object:removeSelf(). Also, since “collectgarbage()” shows only the Lua memory, it’s not a perfect representation of the memory being used when you load/unload image sheets… this is why if you test a load + unload of image sheets while running a Lua memory checker loop, the numbers may not “add up” as you expect, but the cleanup is occurring at the core level.

Hope this helps,

Brent

Thanks for clearing things up, the old sprite API had a dispose() function and while I was searching the forum I had a read thru the “[Tips] Optimization 101” thread and didn’t see anything about imageSheets so I just started wondering…

Another question…

What is best to use for static objects (backgrounds, logos, anything not animated…), newSprite() or newImageRect()???

I think that newImageRect(), becaue newSprite() is usually for animated or changing(switching) images. With newSprite() you must always define sequence data. Both methods uses imageSheet. So newImageRect() will handle both  sheets and image filename, where sprite needs sheet with animation.

When I have button which will change it looks when interacted then I create image sheet and spirte with only one sequence having all images. Then on change I use setFrame() to change look.

If I have some more similar images or images which appears a lot, then it’s smarter to pack everything into sheet (be aware sheet sizes are limited, so sometimes you have to break it into smaller sheets to fit size restrictions) and load images through newImageRect( imageSheet, frame, frameWidth, frameHeight) - this cannot be animated, you just create image from part of sheet. Thanks to that you do not have to load image each time but only once (sheet). Then you just dynamicaly take parts of this sheet to create images (so it’s a lot more efficient)

If I have backgrounds, logos etc (big or unique images) then I load them through newImageRect( filename, imageWidth, imageHeight )