【问题标题】:How can I loop through UITableView's cells?如何循环遍历 UITableView 的单元格?
【发布时间】:2011-10-18 08:32:21
【问题描述】:

我有 n 个部分(已知数量)和 X 行在每个部分(未知数量。每一行都有一个 UITextField。当用户点击“完成”按钮时,我想遍历每个单元格并使用UITextField。如果测试通过,每个单元格中的数据被写入数据库。如果没有,则显示 UIAlert。循环遍历行的最佳方法是什么,如果有更优雅的解决方案,请提供建议。

【问题讨论】:

  • 不要这样做(可能的例外是您有一个小表格,并且已将单元格定义为不可重用)。使用 tableviews 的推荐方法是在单独的 model 中维护状态。 当用户进行更改时,您可以使用更改更新该模型,方法是将处理程序添加到每个字段的 editDidEnd 或类似方法。然后当“完成”时,您正在检查您的自定义模型数据 - 不需要显示的字段。

标签: ios uitableview


【解决方案1】:

如果您只想遍历可见单元格,请使用

NSArray *cells = [tableView visibleCells];

如果你想要表格视图的所有单元格,那么使用这个:

NSMutableArray *cells = [[NSMutableArray alloc] init];
for (NSInteger j = 0; j < [tableView numberOfSections]; ++j)
{
    for (NSInteger i = 0; i < [tableView numberOfRowsInSection:j]; ++i)
    {
        [cells addObject:[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:j]]];
    }
}

现在您可以遍历所有单元格:
CustomTableViewCell是一个类,包含UITextField类型的属性textField

for (CustomTableViewCell *cell in cells)
{
    UITextField *textField = [cell textField];
    NSLog(@"%@"; [textField text]);
}

【讨论】:

  • 不,子类化对此没有任何影响。 cells 是一个数组,其中包含所有类型为 CustomTableViewCell 或其他类型的 tableview 单元格。
  • 我发现我必须删除 numberOfSections 和 numberOfRowsInSection 上的 intValue 运算符。不过,这正是我想要的,谢谢。
  • 确实,不确定是否改变了,但是 numberOfSections 和 numberOfRowsInSection 都已经返回了一个 NSInteger。
  • 只有这个答案的第一部分是有效的。第二部分没有意义。如果您循环并修改表格视图的所有单元格,并认为每一行都有一个单元格实例,那么您并不真正了解表格视图的工作原理。
  • 当一行离开视野时,它的单元格被刚刚进入视野的一行重用。所以基本上你需要在“它的”单元格之外维护每一行的状态(可能在一个数组中)。要一次修改所有行,请更新这样的数组并让 TableView 的 GetCell 方法在每行的单元格下一次变为可见时对其进行修改。
【解决方案2】:

这是一个适合我的不错的快速实现。

 func animateCells() {
        for cell in tableView.visibleCells() as! [UITableViewCell] {
            //do someting with the cell here.

        }
    }

【讨论】:

    【解决方案3】:

    对于不了解 ObjC 的人(比如我),迅速接受答案。

    for section in 0 ..< sectionCount {
        let rowCount = tableView.numberOfRowsInSection(section)
        var list = [TableViewCell]()
    
        for row in 0 ..< rowCount {
            let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: row, inSection: section)) as! YourCell
            list.append(cell)
        }
    }
    

    【讨论】:

      【解决方案4】:

      对于 xcode 9 使用这个 - (类似于 @2ank3th 但代码已更改为 swift 4):

      let totalSection = tableView.numberOfSections
      for section in 0..<totalSection
      {
          print("section \(section)")
          let totalRows = tableView.numberOfRows(inSection: section)
      
          for row in 0..<totalRows
          {
              print("row \(row)")
              let cell = tableView.cellForRow(at: IndexPath(row: row, section: section))
              if let label = cell?.viewWithTag(2) as? UILabel
              {
                  label.text = "Section = \(section), Row = \(row)"
              }
          }
      }
      

      【讨论】:

      • 感谢您的帮助!
      【解决方案5】:
      for (UIView *view in TableView.subviews) {
          for (tableviewCell *cell in view.subviews) {
             //do
          }
      }
      

      【讨论】:

      • 并非所有 TableView 的孩子都是单元格。
      • 在假设它们是 UITableViewCells 之前检查这些子视图的类
      • 这里需要设置条件并检查isKindOfClass:,然后再进行下一个循环,内循环也是如此。
      【解决方案6】:

      由于 iOS 可能会回收屏幕外的 tableView 单元格,因此您必须一次处理一个单元格:

      NSIndexPath *indexPath;
      CustomTableViewCell *cell;
      
      NSInteger sectionCount = [tableView numberOfSections];
      for (NSInteger section = 0; section < sectionCount; section++) {
          NSInteger rowCount = [tableView numberOfRowsInSection:section];
          for (NSInteger row = 0; row < rowCount; row++) {
              indexPath = [NSIndexPath indexPathForRow:row inSection:section];
              cell = [tableView cellForRowAtIndexPath:indexPath];
              NSLog(@"Section %@ row %@: %@", @(section), @(row), cell.textField.text);
          }
      }
      

      只有在整个列表可见时,您才能预先收集所有单元格的 NSArray。在这种情况下,请使用 [tableView visibleCells] 以确保安全。

      【讨论】:

        【解决方案7】:

        又快又脏:

        for (UIView *view in self.tableView.subviews){
            for (id subview in view.subviews){
                if ([subview isKindOfClass:[UITableViewCell class]]){
                    UITableViewCell *cell = subview;
                    // do something with your cell
                }
            }
        }
        

        【讨论】:

        • 其实没有测试这个...所以可能有不可见单元格的问题:/谨慎使用:)
        【解决方案8】:

        这是考虑循环遍历 UITableView 行的一种完全不同的方式......这是一个通过循环遍历数组来更改可能填充 UITextView 的文本的示例,本质上意味着您的 tableView 单元格数据。

        所有单元格都填充有来自某种模型的数据。一个非常常见的模型是使用这些对象的 NSObject 和 NSMutableArray。如果你在 didSelectRowAtIndexPath 中,那么你会想要做这样的事情来影响你在修改上面的数组后选择的行:

        for(YourObject *cellRow in yourArray)
        {
            if(![cellRow.someString isEqualToString:@""])
            {
                 cellRow.someString = @"";
            }
            //...tons of options for conditions related to your data
        }
        
        YourObject *obj = [yourArray objectAtIndex:indexPath.row];
        obj.someString = @"selected";
        [yourArray insertObject:views atIndex:indexPath.row];
        [yourArray removeObjectAtIndex:indexPath.row];
        [yourTable reloadData];
        

        只要您使用 obj.someString 在 cellForRowAtIndexPath 或 willDisplayRowAtIndexPath 中填充该字段的文本,此代码将删除每一行中的所有 UITextField 文本,除了您选择的那一行使用 YourObjectyourArray

        这种类型的“循环”不需要可见单元格与不可见单元格的任何条件。如果您有多个由字典数组填充的部分,则可以通过对键值使用条件来使用相同的逻辑。也许您想切换单元格 imageView,您可以更改表示图像名称的字符串。在不使用任何委托的 UITableView 属性的情况下循环遍历 tableView 中的数据的大量选项。

        【讨论】:

          猜你喜欢
          • 2021-06-28
          • 1970-01-01
          • 1970-01-01
          • 2019-04-02
          • 1970-01-01
          • 1970-01-01
          • 2019-10-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多