TableView deleting row contents after scrolling them off display

Is anyone else having this weird problem.

I create a tabelview and insert images into each row. This works fine until I scroll the view past these images. When I then go to scroll back up the tablerows. I get an error when my row renderer is trying to set the width of the row.

It appears from the error that the row’s image has been deleted from memory, even though the image is only inserted into the row but, is a field of a different object, which gliders debugger shows still exists. It seems the table is somehow deciding it has some idiotic right to delete whatever was inserted into it’s rows if the object becomes non-visible.

Here is the offending on render code. Note that this works fine the first time the rows are inserted but, not when scrolling back through the table. It then fails with the following error

local function onRowRender( event )

    local row = event.row

    

    print("row index " … row.id)

    

    if Images[row.id] == nil then

        return

    else

        if Images[row.id].background ~= nil then

       

        Images[row.id].background.x = crossSaleAdverts[row.id].background.width / 2

        Images[row.id].background.y = crossSaleAdverts[row.id].background.height / 2

        

        Images[row.id].background.width = row.contentWidth

        Images[row.id].background.height = row.contentHeight

        row:insert(Images[row.id].background);

        end

    end

end

The error

stack traceback:

    ?: in function <?:218>

    [C]: ?

    /Users/petedwye/Library/Application Support/luaglider2/dev/ProjectBuilds/CrossSale(Builds)/CrossSale(default)/CrossSale/main.lua:54: in function ‘_onRowRender’

    ?: in function ‘_createRow’

    ?: in function ‘_manageRowLifeCycle’

    ?: in function <?:512>

    ?: in function <?:218>

    

Hi @penhalion0,

This is how tableView works, and always has. When rows move offscreen, they are cleared and the contents removed to conserve texture memory. Then, when the row comes back onscreen, it is “re-rendered” to restore that row to how it was.

Best regards,

Brent

Hi Brent,

That’s fine but, in this instance the table is not re-rendering anything. It’s throwing an exception and the texture is now null! So the table is removing the texture completely from corona! Are you saying that I have to reload the texture each time! I want to render the row!

Can you post the code of your onRowRender function?

That would help us help you :slight_smile:

It’s in the very first post on this thread :slight_smile:

It’s a simple little function to center my add in the row and that’s it. It always fails on the second pass through i.e. the redisplay of a previously visible and then hidden row. It fails on this line

Images[row.id].background.x = crossSaleAdverts[row.id].background.width / 2

with an error that width is a nil value. Meaning that the table has not in fact restored anything for that row.

By the way just to test I wasn’t going mad both crossSaleAdvert and Images are actually identical tables referencing the same images. previously I just used images and thought that maybe this was being deleted somewhere but, if it is, it’s not by me!

Indeed, sorry I missed that.

However, you didn’t post the code that shows you creating the images, only positioning them.

Can you post that part up?

:slight_smile:

It’s a single line in my class that is

Images.background = display.newImage( imagename … “background.ping”);

The images show the first time no problem and I can stop the error by reloading the image every time the onRowRender is called so it’s definitely being deleted by tableView.

Yes. That should be put in your onRowRender function.

You should be creating the image in your onRowRender function, so that when the row goes off screen and the row render function is called again, it re-creates the image you see.

The way you have it right now, it won’t re-create the image.

The tableView is designed to remove rows that go off screen. The process is like this:

  1. Row on screen > render row (call onRowRender)

  2. Row off screen > remove row

  3. Row back on screen > render row (call onRowRender)

Yes I corrected this already. I’m just surprised that instead of simply removing the image from the rows group it is also deleting the image from memory so that anything that tries to or shares the image is suddenly left with nil references. Surely that can not have been the intended functionality.

I think that was exactly the intended functionality! Think of the memory demands on less-capable devices with large TableViews otherwise.

If you don’t like the way this works you can always roll your own with the open-source widgets or use a ScrollView.

I doubt that’s intended functionality as the images are not just removed from the table. They become invalid everywhere they are used!

Hi @penhalion0,

This is how tableView works, and always has. When rows move offscreen, they are cleared and the contents removed to conserve texture memory. Then, when the row comes back onscreen, it is “re-rendered” to restore that row to how it was.

Best regards,

Brent

Hi Brent,

That’s fine but, in this instance the table is not re-rendering anything. It’s throwing an exception and the texture is now null! So the table is removing the texture completely from corona! Are you saying that I have to reload the texture each time! I want to render the row!

Can you post the code of your onRowRender function?

That would help us help you :slight_smile:

It’s in the very first post on this thread :slight_smile:

It’s a simple little function to center my add in the row and that’s it. It always fails on the second pass through i.e. the redisplay of a previously visible and then hidden row. It fails on this line

Images[row.id].background.x = crossSaleAdverts[row.id].background.width / 2

with an error that width is a nil value. Meaning that the table has not in fact restored anything for that row.

By the way just to test I wasn’t going mad both crossSaleAdvert and Images are actually identical tables referencing the same images. previously I just used images and thought that maybe this was being deleted somewhere but, if it is, it’s not by me!

Indeed, sorry I missed that.

However, you didn’t post the code that shows you creating the images, only positioning them.

Can you post that part up?

:slight_smile:

It’s a single line in my class that is

Images.background = display.newImage( imagename … “background.ping”);

The images show the first time no problem and I can stop the error by reloading the image every time the onRowRender is called so it’s definitely being deleted by tableView.

Yes. That should be put in your onRowRender function.

You should be creating the image in your onRowRender function, so that when the row goes off screen and the row render function is called again, it re-creates the image you see.

The way you have it right now, it won’t re-create the image.

The tableView is designed to remove rows that go off screen. The process is like this:

  1. Row on screen > render row (call onRowRender)

  2. Row off screen > remove row

  3. Row back on screen > render row (call onRowRender)

Yes I corrected this already. I’m just surprised that instead of simply removing the image from the rows group it is also deleting the image from memory so that anything that tries to or shares the image is suddenly left with nil references. Surely that can not have been the intended functionality.

I think that was exactly the intended functionality! Think of the memory demands on less-capable devices with large TableViews otherwise.

If you don’t like the way this works you can always roll your own with the open-source widgets or use a ScrollView.