UITableViewDelegate 中的问题 - RowSelected 给出错误的 NSIndexPath [英] Problem in UITableViewDelegate - RowSelected gives wrong NSIndexPath

查看:20
本文介绍了UITableViewDelegate 中的问题 - RowSelected 给出错误的 NSIndexPath的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 UITableViewSource 子类.我正在覆盖 GetCell 并使用我自己的子类单元格,如下所示:

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;
}

这有效,但是当我在 UITableViewDelegate 中获取事件时,索引路径让我得到错误的单元格(AccessoryButtonTapped、WillSelectRow 等事件).

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.)

注意事项:

  • 表格不断更新 - 项目到达不同的线程,然后被 InvokeOnMainThread'd
  • 尽管表格不断更新,但只添加了行和节 - 没有重新排序或删除任何内容
  • 如果我在收到WillSelectRow"时暂停更新,则无济于事
  • 最有趣的是(但不是可交付的解决方案),如果我每次都创建一个新单元而不是执行 DequeueReusableCell,它可以正常工作.

我不禁认为这是我自己制造的一个愚蠢的错误,但找不到它.任何帮助将不胜感激!

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!

推荐答案

您可以尝试不同的方法,如下所示:http://simon.nureality.ca/?p=91

You could try a different approach as demonstrated on: http://simon.nureality.ca/?p=91

基本上,不要将 UITableViewCell 子类化,而是将 UIViewController 子类化为MarketCellController".这个自定义控制器维护一个标准的 UITableViewCell 以及您的自定义内容,并通过 AddSubview() 简单地添加您的自定义内容.

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.

快速示例:

Dictionary<int,MarketCellController> controllers = new Dictionary<int,MarketCellController>();

// ...

public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) {
  UITableViewCell cell = tableView.DequeueReusableCell(_cellIdentifier);
  MarketCellController cellController;

  if (cell == null) {
    cellController = new MarketCellController();
    cell = cellController.Cell;
    controllers.Add(cell.Tag, cellController);
  } else {
    cellController = controllers[cell.Tag];
  }

  // Decorate the cell (using Methods of your cellController)
  // ...

  return cell;
}

这最终可以避免子类 UITableViewCells 和出列问题.

This could eventually circumvent problems with subclassed UITableViewCells and dequeuing.

我只是想到了另外一件事:您似乎只是在 MarketCell 构造函数上分配您的项目.但是,出列的单元格设置了旧项,出列后需要将其重置为新项.

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.

移除构造函数的 item 参数(它无论如何都会被覆盖)并创建一个公共属性(或 setter).在获取单元格后使用它来分配正确的项目(无论它是出队的还是新创建的).应该这样做:

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:

MarketCell cell = tableView.DequeueReusableCell(_cellIdentifier) as MarketCell;
if (cell == null) {
  cell = new MarketCell(UITableViewCellStyle.Subtitle, _cellIdentifier);
}

// Assign the correct item
cell.Item = item;
// or (whatever you like more):
// cell.SetItem(item);

// Decorate the cell
// ...

return cell;

我的 cellController 方法也是如此.无论单元是出队还是新单元,您都应该始终重置单元上可能与任何其他单元不同的所有内容.

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.

顺便说一句:如果您将单元格硬编码为 UITableViewCellStyle.Subtitle,您也可以从构造函数中省略它并将其硬编码到 MarketCell 类中.

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.

至于 cellController 方法的价值:您将 UITableViewCell 与您的自定义数据和行为分离,从而获得一个很好的分离层.您的单元格控制器不必像表格单元格一样工作 ;)

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 ;)

这篇关于UITableViewDelegate 中的问题 - RowSelected 给出错误的 NSIndexPath的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆