【问题标题】:Reload UITableView Data without repositioning UITableViewCells重新加载 UITableView 数据而不重新定位 UITableViewCells
【发布时间】:2012-07-25 11:28:25
【问题描述】:

我有一个从 NSFetchedResultsController 接收数据的 UITableView。 NSFetchedResultsController 的数据偶尔会被网络调用更新。每次通过网络调用更新数据后,我都会使用 [tableView reloadData] 更新 UITableView 以添加任何新项目。

我的部分 UI 还允许水平重新定位单元格。我希望每次刷新表格数据时不要重新定位这些单元格,但不幸的是,[tableview reloadData] 就是这样做的。

在不重新定位其行的情况下更新 tableview 中的数据的理想方法是什么?我应该覆盖 tableview 的 reloadData 方法并在那里做一些花哨的事情,或者可能覆盖 tableview 单元格 layoutSubviews 方法吗?

我这样定位单元格:

CGRect newFrame = cell.frame;
newFrame.origin.x = -cell.frame.size.width;
cell.frame = newFrame;

NSFetched Results Controller 从网络调用接收到更多数据后,调用它的委托方法:

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.eventTableView reloadData];
}

调用 tableview: cellForRowAtIndexPath: 并且从出队返回的单元格的原点位于 (0,0)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath    *)indexPath
{
    static NSString *CellIdentifier = @"EventCell";
    EventCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        [cellNib instantiateWithOwner:self options:nil];
        cell = self.customCell;
    }

    // Configure the cell...
    Event *event = [fetchedResultsController objectAtIndexPath:indexPath];
    [cell configureCellWithEvent:event];

    return cell;
}

【问题讨论】:

  • 你能说得更具体点吗?也许发布一些关于这种重新定位是如何发生的代码,因为否则很难提出替代方案。
  • @Dima 没有太多代码可以发布,因为大部分代码都发生在 Apple 的 [tableView reloadData] 实现中。我通过修改它们的框架来移动单元格,当我调用[tableView reloadData]时,从[tableView dequeueReusableCellWithIdentifier:CellIdentifier] 返回的单元格的原点位于 (0, 0)。
  • 可能有更好的方法来做到这一点,但是为单元格创建一个自定义视图然后让单元格监听更新并自行更新呢?

标签: ios layout uitableview nsfetchedresultscontroller


【解决方案1】:

您可以尝试 UITableViewDelegate 方法tableView:willDisplayCell:forRowAtIndexPath:,该方法在任何单元格添加到表格视图或滚动到表格的可见区域之前调用。在那里,您可以根据需要定位单元格,这将在重新加载后起作用。

这对您的问题并不重要,但我还建议更改单元格的变换属性而不是其框架。这样一来,您就不会意外地将其移动得超出您的预期(例如,如果您移动了两次)。

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
  //Determine if the cell should be shifted.
  if (cellShouldShift) {
     cell.transform = CGAffineTransformMakeTranslation(0 - cell.bounds.size.width, 0);
  } else {
     cell.transform = CGAffineTransformIdentity;
  }
}

【讨论】:

  • 此方法在 cellForRowAtIndexPath 之后调用,此时单元格已设置为其原点。因此,如果我知道该单元之前是否被移动过,我可以在那里完成同样的事情。困难的部分是确定单元格在重新加载之前是否曾被移动过。我想我可以在单元格上保留某种标记属性,但这似乎有点 hacky。
  • 在需要时插入行(使用insertRowsAtIndexPaths:withRowAnimation:)而不是重新加载表视图是否可行?如果没有,你可能不得不求助于一些 hacky。
  • 我想我不得不求助于一些 hacky,因为网络调用也包含更新已经存在的单元格 UI 的信息。 :(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多