【问题标题】:how to obtain the UITableViewCell within heightForRowAtIndexPath?如何在 heightForRowAtIndexPath 中获取 UITableViewCell?
【发布时间】:2011-03-10 02:17:59
【问题描述】:

heightForRowAtIndexPath 方法中,即给定indexPath,如何获得UITableViewCell

(然后我可以访问我创建的内容视图来增加它们的高度)

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
  // How to get the UITableViewCell associated with this indexPath?
}

谢谢

编辑:实际上真的有有效的方法来做到这一点吗?当我放一些NSLog 语句时,似乎heightForRowAtIndexPath 在调用cellForRowAtIndexPath 之前调用了几次(这是我在单元格中设置UILabels 的地方)?这种暗示我可能会尝试使用一种不起作用的技术,即我希望在heightForRowAtIndexPath 中访问每个单元格中已经创建的标签以获取它们的高度并将它们加在一起以获得整个单元格行高度,但是如果它们还没有设置好(在cellForRowAtIndexPath 内),那么我想我的方法真的行不通吗?

【问题讨论】:

    标签: iphone ios uitableview heightforrowatindexpath


    【解决方案1】:

    您可以使用 tableview 的委托而不是 tableView 本身。

    id cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
    

    查看答案here

    更新

    在新的 iOS 版本中并使用正确的自动约束,您不再需要引用单元格来计算单元格的高度。

    检查这里

    https://www.raywenderlich.com/129059/self-sizing-table-view-cells

    【讨论】:

    • 完美,这是这个问题的正确答案!
    • 我很好奇使用这种方法有什么缺点。表视图委托需要与表视图数据源紧密耦合吗?
    • 这是一个无限循环
    • 这是一个无限循环[2]
    • 这是一个无限循环[3]
    【解决方案2】:

    这个问题没有意义,因为在

    heightForRowAtIndexPath
    

    尚未创建任何单元格。下面是 tableView 的工作原理:

    1. TableView 询问它的数据源它将有多少个部分。 -numberOfSectionsInTableView
    2. 询问它的数据源每个部分将有多少行(知道滚动条应该有多大等)-numberOfRowsInSection
    3. 询问每个可见行的代表高度。知道细胞的位置。 - heightForRowAtIndexPath
    4. 最后它要求数据源给它一个单元格显示在给定的索引路径-cellForRowAtIndexPath

    因此您无法从heightForRowAtIndexPath 访问单元格,因为最有可能的单元格尚未创建。


    但是,如果我误解了您的问题,请尝试:

    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    

    【讨论】:

    • 这是一个无限循环
    【解决方案3】:

    显而易见的答案是致电cellForRowAtIndexPath,但您可能已经发现其中存在一些问题。如果您还没有,请查看此问题:UITableView flexible/dynamic heightForRowAtIndexPath

    在我的上一个项目中,我使用了 UICell 的自定义子类并实现了这样的方法。然后我从table:heightForRowAtIndexPath: 调用它(在查找该行的内容之后)。

    + (CGFloat) heightOfContent: (NSString *)content
    {
        CGFloat contentHeight = 
               [content sizeWithFont: DefaultContentLabelFont
                   constrainedToSize: CGSizeMake( DefaultCellSize.width, DefaultContentLabelHeight * DefaultContentLabelNumberOfLines )
                       lineBreakMode: UILineBreakModeWordWrap].height;
        return contentHeight + DefaultCellPaddingHeight;
    }
    

    【讨论】:

    • 糟糕,KingofBliss 在我创建答案时发布。并不意味着我提到的“显而易见的答案”是个人的!
    • SizeWithFont 在 iOS 7 中似乎已被弃用,我们现在该怎么做?
    • @MartindeKeijzer 看这里:stackoverflow.com/questions/18897896/…
    【解决方案4】:

    我建议您使用您的数据结构(文本、图像、多行文本等的高度)计算 table:heightForRowAtIndexPath: 中行的正确高度。

    并在他们的-(void) layoutSubviews 方法中更改组件高度。

    【讨论】:

    • 我目前只有一些 UILabel 堆叠在 UITableViewCell 中。我目前正在 cellForRowAtIndexPath 方法中的单元格内设置 UILables 的定位。这个可以吗?所以我打算整体布局cellForRowAtIndexPath中单元格中的标签,然后在heightForRowAtIndexPath中设置UITableViewCell行高。这样可以吗?
    • @Greg :如果您使用的 UILables 多于一个,建议您创建一个 CustomCell 类,该类将从 UIViewTableCell 单元格继承,并且在 customcell 的 -(void) layoutSubviews 函数中,您可以为您的UILable 的根据您的要求,
    • @Greg :我不建议您在“cellForRowAtIndexPath”或“heightForRowAtIndexPath”中设置标签的布局,并且我的方法中最好的部分是您将获得一个需要的可重用自定义单元格组件更少的维护。
    • 感谢您的领导-目前我只是想了解这种方法-以后可能会转向另一种方法(根据我的阅读,这两种方法都有优缺点)
    【解决方案5】:

    如果您想访问单元格,请使用标签。但正如@Jhaliya 所说,最好根据单元格的内容计算高度。如果您关心的是单元格的位置,那么我建议您使用滚动视图并自己实现单元格。

    【讨论】:

      【解决方案6】:

      对于iOS8

      override func viewDidLoad() {
              super.viewDidLoad()
      
              self.tableView.estimatedRowHeight = 80
              self.tableView.rowHeight = UITableViewAutomaticDimension
          }
      

      func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
                  return UITableViewAutomaticDimension
      
          }
      

      但是对于iOS7,关键是计算自动布局后的高度,

      func calculateHeightForConfiguredSizingCell(cell: GSTableViewCell) -> CGFloat {
              cell.setNeedsLayout()
              cell.layoutIfNeeded()
              let height = cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingExpandedSize).height + 1.0
              return height
      
          }
      

      注意:

      1) 如果是多行标签,不要忘记将numberOfLines 设置为0。

      2) 不要忘记label.preferredMaxLayoutWidth = CGRectGetWidth(tableView.bounds)

      【讨论】:

      • 我在尝试此操作时收到此错误:*** 由于未捕获的异常 'NSInvalidArgumentException' 导致应用程序终止,原因:'-[MyController cellForRowAtIndexPath:]:无法识别的选择器已发送到实例 0x4d21470'
      • 这似乎创建了一个递归循环,反复运行“heightForRowAtIndexPath”。实际上,在调用 cellForRowAtIndexPath 以创建单元格之前,放入一些 NSLog 语句似乎它调用了几次 heightForRowAtIndexPath ?这种意味着我可能会尝试使用一种不起作用的技术,即我希望在 heightForRowAtIndexPath 中访问每个单元格中已经创建的标签以获取它们的高度并将它们加在一起以获得整个单元格行高,但是如果他们尚未设置(在 cellForRowAtIndexPath 内)?
      • 实际上我意识到,就具体而言,我想这个答案是正确的(但这是我如何使用它的问题,因为此时单元格尚未完全设置时间?) - 所以在这种情况下我应该标记为答案
      • 你说得对,它们还没有设置好,你可能会陷入递归循环。这就是为什么您可能希望退回到只计算单元格的高度。您在下面尝试了我的解决方案吗?应该可以解决您的问题。
      • 为什么这个答案有这么多反对意见?是因为预编辑错误还是还是有问题?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-26
      • 2013-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-20
      相关资源
      最近更新 更多