I have a UITableViewSource which I have subclassed. I’m overriding GetCell and using my own subclassed cells, like so:
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
MarketItem item=_tableItems[indexPath.Section].Items[indexPath.Row];
MarketCell cell=tableView.DequeueReusableCell(_cellIdentifier) as MarketCell;
if (cell==null)
{
cell=new MarketCell(UITableViewCellStyle.Subtitle,_cellIdentifier,item);
}
// decorate the cell
// ...
return cell;
}
This works but when I get events in my UITableViewDelegate, the index path gets me the wrong cell (events like AccessoryButtonTapped, WillSelectRow etc).
The Section and Row numbers look correct but when I do a
tableView.CellAt(indexPath)
I get the wrong cell. (The row and section numbers again look correct.)
Things to note:
- The table is constantly being updated – items arrive in a different thread which are then InvokeOnMainThread’d
- Although the table is constantly updated, rows and sections are only added – nothing is re-ordered or deleted
- If I pause the updates when I get a ‘WillSelectRow’, it doesn’t help
- Most interestingly (but not a shippable solution) if I make a new cell each time rather than doing DequeueReusableCell, it works correctly.
I can’t help thinking it’s a stupid bug of my own making but can’t find it. Any help would be most gratefully received!
You could try a different approach as demonstrated on: http://simon.nureality.ca/?p=91
Basically, don’t subclass UITableViewCell but instead subclass UIViewController as “MarketCellController”. This custom controller maintains a standard UITableViewCell as well as your custom stuff and simply adds your custom stuff via AddSubview().
You create one new controller for each required cell and store them into a dictionary.
The trick: By assigning unique tags to the cells, you can retrieve the associated controller from the dictionary.
Quick example:
This could eventually circumvent problems with subclassed UITableViewCells and dequeuing.
EDIT:
I just had something else in mind: You seem to be only assinging your items on your MarketCell constructor. However, dequeued cells have their old item set and you need to reset it to the new item after dequeuing.
Remove the item parameter of the constructor (it’ll be overwritten anyways) and create a public property (or setter) instead. Use that to assign the correct item after fetching the cell (regardless if it was dequeued or newly created). That should do:
The same goes for my cellController approach as well. No matter if a cell was dequeued or new, you should always reset everything on the cell that could possibly differ from any other cells.
BTW: If you hard-code your cells to UITableViewCellStyle.Subtitle, you could just omit it from the constructor as well and hard-code it into your MarketCell class.
As for what the cellController approach is worth: You decouple the UITableViewCell from your custom data and behaviour and thus get a nice layer of separation. Your cell controller does not have to act like a table cell 😉