TableView:getRowAtIndex returns nil on valid rows

TableView::GetRowAtIndex returns nil for valid rows.

Here’s sample code

local widget = require( "widget" ) -- hide device status bar display.setStatusBar( display.HiddenStatusBar ) function onRowRender(event) local t = nil if (event.row.params == nil) then t = event.target.categoryName else t = "" .. event.row.params.text end local myText = display.newText( event.row, t, 100, 10, native.systemFont, 16 ) myText:setFillColor( 1, 0, 0 ) end local tableView = widget.newTableView { left = 0, top = 20, height = display.contentHeight, width = display.contentWidth, onRowRender = onRowRender, onRowTouch = onRowTouch, listener = scrollListener, noLines = true } -- Insert 40 rows for i = 1, 40 do local isCategory = false local rowHeight = 36 local rowColor = { default={ 1, 1, 1 }, over={ 1, 0.5, 0, 0.2 } } local lineColor = { 0.5, 0.5, 0.5 } tableView.categoryName = "Category " .. i -- Make some rows categories if ( i % 10 == 0 ) then isCategory = true rowHeight = 40 rowColor = { default={ 0.8, 0.8, 0.8, 0.8 } } lineColor = { 1, 0, 0 } end -- Insert a row into the tableView tableView:insertRow( { isCategory = isCategory, rowHeight = rowHeight, rowColor = rowColor, lineColor = lineColor, params = { text = "Row" .. i } } ) end for i = 1, 40 do local rowAtIndex = tableView:getRowAtIndex( i ) if (rowAtIndex == nil) then local totalRows = tableView:getNumRows() print ("Bug. Row at index " .. i .. " shouldn't be nil. Total Rows = " .. totalRows) end end

Is the row in question on the screen?   The docs have this in the “Gotcha’s” area:

This function will return nil if the row is not currently visible in the table view.

See: http://docs.coronalabs.com/api/type/TableViewWidget/getRowAtIndex.html

Rob

Yes the rows in question are visible on the screen. In the above example, no row is hidden.

I tried tableView:getRowAtIndex( i ) in one of CL samples and it worked well. I then wondered if its the use of params which is still causing some troubles in some scenarios I believe so I put in params into the sample and it still works. Not sure what specifically is causing the issue in above code but seems like the core functionality of tableView:getRowAtIndex( i ) is working well. 

Ok. I tried the code above and I see that Rob’s assertion of the Gotcha is what’s happening. When I run it in my simulator (iPhone5 running landscape) I see 20 rows on screen. The printout starts with row 23 and goes up to row 40 such as : 

Bug. Row at index 23 shouldn’t be nil. Total Rows = 40    

Bug. Row at index 24 shouldn’t be nil. Total Rows = 40    

… sequential rows deleted …

Bug. Row at index 40 shouldn’t be nil. Total Rows = 40    

So the tableView:getRowAtIndex( i ) works with the caveat noted above. 

Sorry for the late reply. Yes it makes sense now. I misunderstood the caveat. Thanks for your reply.

Is the row in question on the screen?   The docs have this in the “Gotcha’s” area:

This function will return nil if the row is not currently visible in the table view.

See: http://docs.coronalabs.com/api/type/TableViewWidget/getRowAtIndex.html

Rob

Yes the rows in question are visible on the screen. In the above example, no row is hidden.

I tried tableView:getRowAtIndex( i ) in one of CL samples and it worked well. I then wondered if its the use of params which is still causing some troubles in some scenarios I believe so I put in params into the sample and it still works. Not sure what specifically is causing the issue in above code but seems like the core functionality of tableView:getRowAtIndex( i ) is working well. 

Ok. I tried the code above and I see that Rob’s assertion of the Gotcha is what’s happening. When I run it in my simulator (iPhone5 running landscape) I see 20 rows on screen. The printout starts with row 23 and goes up to row 40 such as : 

Bug. Row at index 23 shouldn’t be nil. Total Rows = 40    

Bug. Row at index 24 shouldn’t be nil. Total Rows = 40    

… sequential rows deleted …

Bug. Row at index 40 shouldn’t be nil. Total Rows = 40    

So the tableView:getRowAtIndex( i ) works with the caveat noted above. 

Sorry for the late reply. Yes it makes sense now. I misunderstood the caveat. Thanks for your reply.

I have that problem to, is that a bug or what?

@IronMan, if the tableView can display 10 total rows and your app has 20 total rows, then 10 of them are on screen, 10 of them are off screen.  If rows 1-10 are on screen, then tableView:getRowAtIndex( i ) will return nil for rows 11-20.

Rob

FYI in my experience the TableView widget will render one or two rows offscreen so they’re ready immediately during a fast scroll event. I haven’t ever measured exactly how many, but I’m pretty sure I’m right.

Otherwise tableView:getRowAtIndex() works as Rob describes.

@Rob, but if I delete the first row and call obj:getRowAtIndex() I get error cause data is nil, but if I delete the last row it’s fine.

so I use print to getNumRow of that table, and the reulst is different from the row that in the table. but if I delete one more then getNumRow get update.

but, I get idea to fix this problem now. but error for nil when row delete then getRowAtIndex() I think is a bug.

Are you saying that:

tableView:deleteRow(1)

tableView:getRowAtIndex(1)

is returning nil when the new row 1 should now be the previous row 2?

Rob

yes, is that a bug or should I use different approach?

<IronMan>: You should reference this topic re: deletion timing: http://forums.coronalabs.com/topic/47558-tableview-20-delete-a-row-without-animation/

Its likely because the code executes so fast, that it could be trying to reference the row right after it’s deleted but before the table has been re-indexed.  As @corona273 mentions, there are animations going on when deleting the row.  There could also be a micro timer in there that could give the row deletion a little async property and it purely could be a race condition.  Try dropping your get index call into a timer with say a 500ms delay and see if that changes the behavior.