2014-12-03 79 views
7

我正在处理一个应用程序,我面临一个奇怪的问题。我在故事板中创建了一个UITableViewController并添加了一个原型单元。在这个单元格中,我添加了一个UILabel元素,这个UILabel占据了整个单元格。我用自动布局设置了它,并添加了左,右,上和下限制。 UILabel包含一些文本。iOS 8 UITableView第一行高度错误

现在,在我的代码,我初始化表视图的的rowHeight和estimatedRowHeight:

override func viewDidLoad() { 
    super.viewDidLoad() 

    self.tableView.rowHeight = UITableViewAutomaticDimension 
    self.tableView.estimatedRowHeight = 50 
} 

我创建单元格如下:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
    var cell : UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("HelpCell") as? UITableViewCell 
    if(cell == nil) { 
     cell = UITableViewCell(style: .Default, reuseIdentifier: "HelpCell") 
    } 
    return cell! 
} 

我在表中返回两行视图。这就是我的问题:第一排的高度是很大的。看来,第二,第三排等都有一个正确的高度。我真的不明白为什么会出现这种情况。有人可以帮我弄这个吗?

回答

15

我不得不在细胞的高度是不正确的第一负载,但滚动起来后的问题细胞的高度是固定的。

我尝试了所有不同的'修复'这个问题,然后最终发现调用self.tableView.reloadData后调用这些函数。

  self.tableView.reloadData() 
      // Bug in 8.0+ where need to call the following three methods in order to get the tableView to correctly size the tableViewCells on the initial load. 
      self.tableView.setNeedsLayout() 
      self.tableView.layoutIfNeeded() 
      self.tableView.reloadData() 

只在初始加载后执行这些额外的布局调用。

我在这里发现了这个非常有用的信息:https://github.com/smileyborg/TableViewCellWithAutoLayoutiOS8/issues/10

更新: 有时你可能需要也是完全配置heightForRowAtIndexPath您的单元格,然后返回计算的单元格高度。看看这个链接的一个很好的例子,http://www.raywenderlich.com/73602/dynamic-table-view-cell-height-auto-layout,特别是关于heightForRowAtIndexPath的部分。

更新2:我还发现它非常有益覆盖estimatedHeightForRowAtIndexPath和供应有所准确行高度估计。如果您的UITableView的单元格可以是各种不同的高度,这非常有用。

这里的estimatedHeightForRowAtIndexPath一个人为的示例实现:

public override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 

    let cell = tableView.cellForRowAtIndexPath(indexPath) as! MyCell 

    switch cell.type { 
    case .Small: 
     return kSmallHeight 
    case .Medium: 
     return kMediumHeight 
    case .Large: 
     return kLargeHeight 
    default: 
     break 
    } 
    return UITableViewAutomaticDimension 
} 

更新3:(!宇豪)UITableViewAutomaticDimension已定于iOS 9。所以你应该是自动调整大小,而不必手动计算单元格的高度。

0

在iOS 8中,分配estimatedRowHeight值会启用新的iOS 8自动行高计算功能。这意味着单元格的高度是从内部使用其内部约束得出的。如果这些限制有什么问题,你会得到奇怪的结果。所以你的电池限制有些问题。他们可能不明确;这是不一致的通常原因。不过,我只能告诉你,因为你没有真正展示/描述约束条件。

+0

我敢肯定,我的约束不是模糊的,因为我只对4个的UILabel约束。你有什么其他的建议可能是错误的? – Devos50 2014-12-03 20:20:11

+1

不要“很确定”。有办法找出你是否有不明确的布局。使用它们。不要使用你的直觉;这是问题,而不是解决方案。如果你知道什么构成了明确的布局,我们不会在这里与你有麻烦,对吗?听我说的是什么。简单的事实是,固定左,右,顶部和底部的4个约束是不够的。你的约束可能不明确。 – matt 2014-12-03 21:39:17

0

我建议删除UILabel的底部约束。它会根据文本调整大小,并且单元格也应调整大小。

如果无法解决问题,请尝试在viewDidLoad()加入以下:

self.tableView.reloadData()

+0

谢谢你的建议,但如果我删除约束,UILabel将不会调整自己的大小。另外,重新加载数据并不能解决问题。 – Devos50 2014-12-03 20:19:24

+0

能否请您分享您的约束与细胞的屏幕截图? – Armin 2014-12-04 03:40:00

2

由于苹果的setNeedsLayout描述说:

此方法不强制立即更新,而是等待下一个更新周期,您可以在更新任何视图之前使用它来使多个视图的布局无效。此行为允许您将所有布局更新合并到一个更新周期,这通常对性能更好。

正因为如此,你应该在dispatch_after block添加的代码所需要行(应与正确的布局被执行)(这将会把你方法RunLoop的队列)。并且您的代码将在需要布局适用后执行。

例子:

- (void)someMethod { 

[self.tableView reloadData]; 

[self.tableView setNeedsLayout]; 

[self.tableView layoutIfNeeded]; 

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 

      //code which should be executed with the right size of table 

     });