Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Is this a bug in tableView or am I missing something?
Started by ammar71 Dec 22 2019 07:27 AM

5 replies to this topic
tableview deleterows index getnumrows getrowatindex

Best Answer Rob Miracle , 22 December 2019 - 06:29 PM

Hi @Ammar71. 

 

Please don't confuse Lua tables with the widget.newTableView() object. Under the hood, widget.newTableView() utilizes at least one Lua table, and the object itself is a Lua table. But this isn't really relevant to your question.

 

I would suggest you maybe take some time and do an Internet search on the term MVC or "Model View Controller". This is a design pattern that the widget.newTableView() is part of. Let me give you a quick primer and then I'll explain how the widget.newTableView() fits in to this.

 

In a Model-View-Controller setup, the Model is the data. Typically a database, it's the rows, columns, schema that defines the underlying data. The "View" is the code that presents the data to the user. The model and the view are supposed to be independent. That is the developers can change the model and it not directly impact the view, while the developers can change the view without ever touching the model. This works because in-between there is a controller that is aware of the of the changes on both ends. The view will ask the controller for a name and the view doesn't care how it gets a name. The controller knows how to to get the "Name" from the database.

 

Corona doesn't exactly implement MVC in this way, mostly because we have zero control over your data. We don't know what the model is. If fact, I wouldn't even say we know what the view is, but the widget.newTableView() is just a tool in your control when you go to create your view.

 

In the simplest of terms, your model will likely be a pure Lua table (not attached to the tableView in any way). You could populate it from an SQLite database, a JSON object, a REST API call using network.request() etc. As long as your data ends up in a Lua table you're good to go.

 

Now you have a tableView() and you get your data into the tableView by calling tableView:insertRow(). Now the widget.newTableView() is just a view into your model and the tableView row's will show the representation of your model's data.

 

 

So now, if you delete a row from the tableView, all you've done is removed it from the view. You've not removed it from your model/data. If you do remove it from your Lua table/model, you can do the table.remove() option (http://docs.coronalabs.com/api/library/table/remove.html) to remove the record from the table and have the index numbers recalculated. But this is a very computationally expensive operation.

 

However, if you need the tableView to re-index to match your data, remove it from your data, remove all rows from the tableView and re-insert them should be fast enough (since it only has to update the on screen rows) that you wouldn't notice the action.  

 

You should never depend on the tableView indexes to represent your data. They are expected to get out of sync. What you should do is store the index of the data in with the tableRow and then use that index to lookup the data to show.

 

Rob

[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

ammar71

[GLOBAL: userInfoPane.html]
ammar71
  • Enthusiast

  • 86 posts
  • Corona SDK

Hi all,

 

If I have a table view with 3 rows and I delete the 2nd row, the table updates correctly and the 2nd row gets deleted but the row indexes are not updated. So after the delete, the first row is at index 1 and the second row (that used to be the third row) is still at index 3.

 

This makes it impossible to go through the items in the table using a loop:

for i = 1, tableView:getNumRows() do
    local r = tableView:getRowAtIndex( i )    
end

The first row will be retrieved correctly. The second row will be nil (because it was deleted) and the loop stops there, so we never get to the third row (which is now the 2nd row).

 

Is this a known issue? is there a way around it?

 

Thanks.

 



[TOPIC: post.html]
#2

agramonte

[GLOBAL: userInfoPane.html]
agramonte
  • Corona Geek

  • 1,307 posts
  • Corona SDK

Everything in Lua is a table. In Lua tables when you delete an item that space stays blank. In my experience it has always been easier to delete the value from the underlying table for the tableview and then regenerate the tableview. Others might have a better solution.


  • ammar71 likes this

[TOPIC: post.html]
#3

ammar71

[GLOBAL: userInfoPane.html]
ammar71
  • Enthusiast

  • 86 posts
  • Corona SDK

Thanks for the reply agramont.

 

When you say the "underlying" table, do you mean the internal table that tableView stores the data in or do you mean the original data I used to fill tableView in the first place?

 

1- If you mean the internal table, how can I access that? If I can acces the table can I reassign the indexes to shift items up in the table?

 

2- If you mean the original data I used to fill the tableView, then I am assuming that I would need to delete the tableView object and recreate it. Since the scene is already showing, the user would see the table disappear and reappear. This wouldn't be a good choice, but if no other way exists, then I guess I would have to do that.



[TOPIC: post.html]
#4

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 26,539 posts
  • Enterprise

  Best Answer

Hi @Ammar71. 

 

Please don't confuse Lua tables with the widget.newTableView() object. Under the hood, widget.newTableView() utilizes at least one Lua table, and the object itself is a Lua table. But this isn't really relevant to your question.

 

I would suggest you maybe take some time and do an Internet search on the term MVC or "Model View Controller". This is a design pattern that the widget.newTableView() is part of. Let me give you a quick primer and then I'll explain how the widget.newTableView() fits in to this.

 

In a Model-View-Controller setup, the Model is the data. Typically a database, it's the rows, columns, schema that defines the underlying data. The "View" is the code that presents the data to the user. The model and the view are supposed to be independent. That is the developers can change the model and it not directly impact the view, while the developers can change the view without ever touching the model. This works because in-between there is a controller that is aware of the of the changes on both ends. The view will ask the controller for a name and the view doesn't care how it gets a name. The controller knows how to to get the "Name" from the database.

 

Corona doesn't exactly implement MVC in this way, mostly because we have zero control over your data. We don't know what the model is. If fact, I wouldn't even say we know what the view is, but the widget.newTableView() is just a tool in your control when you go to create your view.

 

In the simplest of terms, your model will likely be a pure Lua table (not attached to the tableView in any way). You could populate it from an SQLite database, a JSON object, a REST API call using network.request() etc. As long as your data ends up in a Lua table you're good to go.

 

Now you have a tableView() and you get your data into the tableView by calling tableView:insertRow(). Now the widget.newTableView() is just a view into your model and the tableView row's will show the representation of your model's data.

 

 

So now, if you delete a row from the tableView, all you've done is removed it from the view. You've not removed it from your model/data. If you do remove it from your Lua table/model, you can do the table.remove() option (http://docs.coronalabs.com/api/library/table/remove.html) to remove the record from the table and have the index numbers recalculated. But this is a very computationally expensive operation.

 

However, if you need the tableView to re-index to match your data, remove it from your data, remove all rows from the tableView and re-insert them should be fast enough (since it only has to update the on screen rows) that you wouldn't notice the action.  

 

You should never depend on the tableView indexes to represent your data. They are expected to get out of sync. What you should do is store the index of the data in with the tableRow and then use that index to lookup the data to show.

 

Rob


  • ammar71 and pixec like this

[TOPIC: post.html]
#5

ammar71

[GLOBAL: userInfoPane.html]
ammar71
  • Enthusiast

  • 86 posts
  • Corona SDK

Thanks @Rob,

 

I did what you suggested (deleting all rows and adding again from my data source) and it worked, but now I don't get the cool "row sliding" effect that was happening when I deleted only one row.



[TOPIC: post.html]
#6

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 26,539 posts
  • Enterprise

You can still delete the rows the way you want, you just have to not match up your data with the row index nor loop over the tableView's rows. 

 

Rob




[topic_controls]
[/topic_controls]

Also tagged with one or more of these keywords: tableview, deleterows, index, getnumrows, getrowatindex