自定义tableview,数据不完整问题

本文探讨了iOS应用中UITableView重用Cell导致的数据显示异常问题,并提供了一种有效的解决方案。通过调整nib注册逻辑,确保每次viewWillAppear时都能正确加载最新数据。

项目中遇到,在注销后重新登录时,自定义的cell中部分数据无法显示。

最终定位到是重用cell的问题。

原来的代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    //使用自定义的CustomCell
    static NSString *CustomCellIdentifier = @"CustomCellIdentifier";
    
    static BOOL nibsRegistered = NO;
    if (!nibsRegistered) {
        UINib *nib = [UINib nibWithNibName:@"CustomCell" bundle:nil];
        [tableView registerNib:nib forCellReuseIdentifier:CustomCellIdentifier];
        nibsRegistered = YES;
    }
    
    CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CustomCellIdentifier];
    if (cell == nil) {
        cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CustomCellIdentifier];
    }
    
    // Configure the cell.
    // to do

    return cell;
}


发现注释掉nibsRegistered = YES后,一切正常。

原因是nibsRegistered是一个静态变量,初始化后,在tableview中的值一直为YES,所以不会再通过registerNib方式重新生成cell。

一般情况下不会有问题,但是当出现跳转到其他viewcontroller并重新拉取数据后,这里的table cell实际上是需要重新做一次初始化的。


修改后的代码如下:

static BOOL nibsRegistered = NO;


@implementation ListViewController

-(void)viewWillAppear:(BOOL)animated
{    
    //保证每次进入都重新注册一次nib
    nibsRegistered = NO;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    //使用自定义的CustomCell
    static NSString *CustomCellIdentifier = @"CustomCellIdentifier";
    
    //static BOOL nibsRegistered = NO;
    if (!nibsRegistered) {
        UINib *nib = [UINib nibWithNibName:@"CustomCell" bundle:nil];
        [tableView registerNib:nib forCellReuseIdentifier:CustomCellIdentifier];
        nibsRegistered = YES;
    }
    
    CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CustomCellIdentifier];
    if (cell == nil) {
        cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CustomCellIdentifier];
    }
    
    // Configure the cell.
    // to do
    
    return cell;
}


### 自定义 Qt TableView 的实现方法 在 Qt 中,`QTableView` 是一个用于展示表格数据的控件,它通常与 `QAbstractTableModel` 或其子类一起使用。为了实现特定的数据展示或交互功能,可以通过继承 `QAbstractTableModel` 并重写其虚函数来创建自定义数据模型,同时也可以通过自定义委托(`QItemDelegate`)来控制单元格的绘制和编辑行为。 #### 自定义数据模型 自定义数据模型需要继承 `QAbstractTableModel` 并实现以下关键函数: - `rowCount()`:返回表格的行数。 - `columnCount()`:返回表格的列数。 - `data()`:返回指定索引处的数据,用于显示、编辑等。 - `headerData()`:返回表头信息。 - `setData()`:用于修改数据,通常在编辑单元格时调用。 示例代码如下: ```cpp class CustomTableModel : public QAbstractTableModel { Q_OBJECT public: int rowCount(const QModelIndex &parent = QModelIndex()) const override { return 10; // 假设表格有10行 } int columnCount(const QModelIndex &parent = QModelIndex()) const override { return 3; // 假设表格有3列 } QVariant data(const QModelIndex &index, int role) const override { if (!index.isValid()) return QVariant(); if (role == Qt::DisplayRole) { return QString("Row %1, Col %2").arg(index.row()).arg(index.column()); } return QVariant(); } QVariant headerData(int section, Qt::Orientation orientation, int role) const override { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { switch (section) { case 0: return "Name"; case 1: return "Age"; case 2: return "Gender"; } } return QVariant(); } }; ``` 上述模型将为 `QTableView` 提供数据,通过 `data()` 方法可以返回同的内容,从而实现自定义数据显示效果。 #### 自定义委托(Delegate) 如果需要进一步控制单元格的绘制或编辑行为,可以自定义委托。例如,可以实现一个自定义的 `QItemDelegate` 来绘制特定的控件或响应特定的交互操作。 以下是一个简单的自定义委托示例,它重写了 `paint()` 和 `createEditor()` 方法: ```cpp class CustomDelegate : public QItemDelegate { Q_OBJECT public: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { if (index.column() == 0) { // 自定义第一列的绘制方式 painter->save(); painter->setPen(Qt::red); painter->drawText(option.rect, Qt::AlignCenter, index.data().toString()); painter->restore(); } else { QItemDelegate::paint(painter, option, index); } } QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override { if (index.column() == 1) { // 第二列使用 QSpinBox 编辑器 QSpinBox *editor = new QSpinBox(parent); editor->setMinimum(0); editor->setMaxmum(100); return editor; } return QItemDelegate::createEditor(parent, option, index); } void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override { if (index.column() == 1) { QSpinBox *spinBox = static_cast<QSpinBox*>(editor); model->setData(index, spinBox->value(), Qt::EditRole); } else { QItemDelegate::setModelData(editor, model, index); } } }; ``` 该委托将第一列的文本绘制为红色,并在第二列中使用 `QSpinBox` 控件进行编辑。通过 `paint()` 和 `createEditor()` 的重写,可以实现更加丰富的用户界面交互。 #### 设置自定义模型和委托 在 `QTableView` 中应用自定义模型和委托的方法如下: ```cpp CustomTableModel *model = new CustomTableModel(this); tableView->setModel(model); CustomDelegate *delegate = new CustomDelegate(this); tableView->setItemDelegate(delegate); ``` 通过这种方式,可以将自定义数据模型和绘制逻辑应用到 `QTableView` 上,从而实现灵活的数据展示和交互功能。 #### 响应用户交互事件 为了实现更复杂的交互逻辑,可以连接 `QTableView` 的信号,如 `clicked()` 或 `doubleClicked()`,以响应用户的点击操作。例如: ```cpp connect(tableView, &QTableView::clicked, this, [this](const QModelIndex &index) { if (index.column() == 2) { // 处理第三列的点击事件 qDebug() << "Gender column clicked at row" << index.row(); } }); ``` 通过这种方式,可以针对特定的列或行实现自定义的交互行为。 #### 总结 自定义 `QTableView` 主要涉及以下几个方面: - 继承 `QAbstractTableModel` 实现自定义数据模型。 - 继承 `QItemDelegate` 实现自定义的绘制和编辑逻辑。 - 使用 `setModel()` 和 `setItemDelegate()` 将模型和委托应用到 `QTableView`。 - 通过信号和槽机制处理用户交互事件。 通过这些步骤,可以构建出功能丰富、界面美观的表格视图,满足特定的业务需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值