【问题标题】:iPad: Iterate over every cell in a UITableView?iPad:遍历 UITableView 中的每个单元格?
【发布时间】:2011-08-04 10:00:46
【问题描述】:

iPad:遍历 UITableView 中的每个单元格?

【问题讨论】:

  • 毫无意义的问题,真的:细胞被汇集和重用。一般来说,如果你没有在屏幕上看到它,它就不存在。请详细说明您要做什么。
  • +1 评论,为什么需要遍历单元格?通常你会迭代你填充单元格的底层数据结构。如果您出于某种原因需要访问单元格,那么在cellForRowAtIndexPath: 中,您可以设置基础数据结构的cell 属性以指向已初始化的单元格。但请确保它是@property (assign),而不是retain,因为您不想为了重用而将所有单元格保留在内存中。
  • 这不是真的没有意义; UITableView 作为一些支持数据存储的可视化表示存在。无论数据的特定子集当前是否在屏幕上,数据存储都存在。因此,迭代单元格类似于查询商店中的内容,一次一行。
  • 毫无意义。如果您正在查询 gui 表,那么您的架构是错误的。您永远不需要在 GUI 上清理表,因为所有数据都存在于数据存储中。该表是 MVC,单元格中包含的所有数据都在基于该模式的数据存储中。这是一个不了解 MVC 工作原理的问题。
  • 我同意尼克·特纳的观点。不要尝试您所描述的内容(可能的例外是您有一个小表格,并且已将单元格定义为不可重用)。使用 tableviews 的推荐方法是在单独的 model 中维护状态。 当用户进行更改时,您可以使用更改更新该模型,方法是将处理程序添加到每个字段的 editDidEnd 或类似方法。然后当“完成”时,您正在检查您的自定义模型数据 - 不需要显示的字段。

标签: ipad uitableview


【解决方案1】:
for (int section = 0; section < [tableView numberOfSections]; section++) {
    for (int row = 0; row < [tableView numberOfRowsInSection:section]; row++) {
        NSIndexPath* cellPath = [NSIndexPath indexPathForRow:row inSection:section];
        UITableViewCell* cell = [tableView cellForRowAtIndexPath:cellPath];
        //do stuff with 'cell'
    }
}

【讨论】:

  • 只对可见单元有效是正常的。不可见的细胞从内存中出列; cellForRowAtIndexPath 将为它们返回 nil。
  • @RaviSharma add [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];它将用于不可见的单元格中。
  • @zaolian - 想想你的建议有什么作用。这是为什么整个方法被误导的一个很好的例子:您正在强制 tableview 从源加载每一行。如果需要的信息在源中,那么这是一个更好的获取它的地方。如果提问者试图从屏幕上读回 changes,那么您的建议似乎有效 - 直到 用户在表格中进行了足够远的更改,滚动回第一行会导致更改的行在此逻辑读取之前被丢弃 - 并永远丢失。
【解决方案2】:

遍历 UITableView 中的每个可见单元格:

for (UITableViewCell *cell in self.tableView.visibleCells) {
    NSIndexPath *cellIndexPath = [self.tableView indexPathForCell:cell];

(经过编辑以更好地说明答案,并希望为搜索结果更准确地编入索引,以便将来为他人节省更多时间)

【讨论】:

  • 这仅适用于可见单元格。
  • 我应该说 - 我更新了我的答案以反映您的评论。
  • +1 用于使用 oop 样式而不是函数方法,即使您不需要这样做,除非您正在更新 GUI 样式。
【解决方案3】:

(这建立在 aroths 的答案之上。)

我喜欢将其定义为UITableView 的一个类别,以便它在任何地方都可用。

(正如多次提到的,你应该确定你真的想要迭代单元格本身。例如:我用它来清除之前所有单元格中的UITableViewAccessoryCheckmark将其设置为用户选择的单元格。一个好的经验法则是仅在数据源方法无法执行您需要的操作时执行此操作。)

这样定义:

- (void)enumerateCellsUsingBlock:(void (^)(UITableViewCell *cell))cellBlock {
    NSParameterAssert(cellBlock != nil);
    for (int section = 0; section < [self numberOfSections]; section++) {
        for (int row = 0; row < [self numberOfRowsInSection:section]; row++) {
            NSIndexPath *cellPath = [NSIndexPath indexPathForRow:row inSection:section];
            UITableViewCell *cell = [self cellForRowAtIndexPath:cellPath];
            if (cellBlock != nil) {
                cellBlock(cell);
            }
        }
    }
}

这样调用:

[self.tableView enumerateCellsUsingBlock:^(UITableViewCell *cell) {
    NSLog(@"cell:%@", cell);
}];

typedef 块也是一种很好的风格。

【讨论】:

    【解决方案4】:

    斯威夫特 4:

    for section in 0...self.tableView.numberOfSections - 1 {
                for row in 0...self.tableView.numberOfRows(inSection: section) - 1 {
                    let cell = self.tableView.cellForRow(at: NSIndexPath(row: row, section: section) as IndexPath)
    
                    print("Section: \(section)  Row: \(row)")
    
                }
            }
    

    史蒂夫 Iterate over all the UITableCells given a section id

    【讨论】:

      【解决方案5】:

      假设存在一个变量myTableView,并且它的委托和数据源都已设置:

      UITableViewCell *cell;
      NSIndexPath indexPath = [[NSIndexPath indexPathForRow:0 inSection:0];
      for(indexPath.section = 0; indexPath.section < [myTableView numberOfSections]; ++indexPath.section)
      {
          for(indexPath.row = 0; indexPath.row < [myTableView numberOfRowsInSection:indexPath.section]; ++indexPath.row)
          {
              cell = [myTableView cellForRowAtIndexPath:indexPath];
              // do something with this cell
          }
      }
      

      【讨论】:

      • 为 indexPath.row 获取这些错误..... 1. 分配给只读属性 2. 增加只读属性....
      • 您不能创建新的NSIndexPath 局部变量。检查 indexPath 不是传递给您的 tableview 数据源函数或类似的东西。
      【解决方案6】:

      更简单更优雅:

      -(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell
                                               forRowAtIndexPath:(NSIndexPath *)indexPath {
          // use the "cell" here
      }
      

      但显然它并不适合所有情况。

      【讨论】:

        【解决方案7】:

        这就是我遍历所有表格视图单元格甚至不可见单元格的方式,请在此处查看我的答案:

        https://stackoverflow.com/a/32626614/2715840

        提示:Swift 中的代码。

        【讨论】:

        • 你的OC版本解决方案,仅供参考:[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-18
        • 1970-01-01
        • 1970-01-01
        • 2018-08-15
        • 1970-01-01
        • 1970-01-01
        • 2021-05-13
        相关资源
        最近更新 更多