我正在创建一个应用程序,它将在UILabel中有一个问题,并在UITableView中显示多项选择的答案,每行显示多项选择。问题和答案会有所不同,所以我需要这个UITableView的高度是动态的。

我想为桌子周围找一个合适的尺寸。其中,表的框架被设置为所有内容的高度。

有人能给我一些建议吗?


当前回答

如果你的contentSize是不正确的,这是因为它是基于估计的rowheight(自动),使用这个之前

tableView.estimatedRowHeight = 0;

来源:https://forums.developer.apple.com/thread/81895

其他回答

Swift 5和4.2解决方案没有KVO, DispatchQueue,也没有自己设置约束。

这个解决方案基于古尔兹的回答。

1)创建UITableView的子类:

import UIKit

final class ContentSizedTableView: UITableView {
    override var contentSize:CGSize {
        didSet {
            invalidateIntrinsicContentSize()
        }
    }

    override var intrinsicContentSize: CGSize {
        layoutIfNeeded()
        return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
    }
}

2)添加一个UITableView到你的布局和设置约束的所有方面。将它的类设置为contentsizetableview。

3)你应该会看到一些错误,因为Storyboard没有考虑子类的intrinsicContentSize。通过打开大小检查器并将intrinsicContentSize重写为一个占位符值来修复此问题。这是设计时的重写。在运行时,它将在contentsizetableview类中使用重写


更新:更改了Swift 4.2的代码。如果你使用的是以前的版本,使用UIViewNoIntrinsicMetric而不是UIView.noIntrinsicMetric

Swift 3, iOS 10.3

解决方案1: 只需将self.tableview.sizeToFit()放在cellForRowAt indexPath函数中。确保tableview的高度比你需要的高。 如果tableview下面没有视图,这是一个很好的解决方案。然而,如果你有,底部tableview约束将不会更新(我没有尝试修复它,因为我想出了解决方案2)

例子:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath) as? TestCell {
        cell.configureCell(data: testArray[indexPath.row])
        self.postsTableView.sizeToFit()
        return cell
    }

    return UITableViewCell()
}

解决方案2: 在故事板中设置tableview高度约束,并将其拖到ViewController中。如果你知道单元格的平均高度,也知道数组包含多少元素,你可以这样做:

tableViewHeightConstraint.constant = CGFloat(testArray.count) * 90.0     // Let's say 90 is the average cell height

*编辑:

在我尝试了所有的解决方案之后,每个解决方案都解决了一些问题,但不是完全解决了问题,这个答案解释并完全解决了这个问题。

我使用的是UIView扩展,方法接近上面的@ChrisB方法

 extension UIView {
func updateHeight(_ height:NSLayoutConstraint)
{
    
    let newSize = CGSize(width: self.frame.size.width, height: CGFloat(MAXFLOAT))
    let fitSize : CGSize = self.sizeThatFits(newSize)
    
    height.constant = fitSize.height
    
   
}
}

实现::

@IBOutlet weak var myTableView: UITableView!
@IBOutlet weak var myTableVieweHeight: NSLayoutConstraint!
//(call it whenever tableView is updated inside/outside delegate methods)
myTableView.updateHeight(myTableVieweHeigh)

好处:可以用在任何其他的uiview,例如:你自己的动态标签

Musa almatri的objc版本

(void)viewWillLayoutSubviews
{
    [super updateViewConstraints];
    CGFloat desiredHeight = self.tableView.contentSize.height;
    // clamp desired height, if needed, and, in that case, leave scroll Enabled
    self.tableHeight.constant = desiredHeight;
    self.tableView.scrollEnabled = NO;
}

事实上,我自己找到了答案。

我只是为tableView.frame创建了一个新的CGRect,它的高度是table.contentSize.height

那将UITableView的高度设置为它内容的高度。 因为代码修改了UI,所以不要忘记在主线程中运行它:

dispatch_async(dispatch_get_main_queue(), ^{
        //This code will run in the main thread:
        CGRect frame = self.tableView.frame;
        frame.size.height = self.tableView.contentSize.height;
        self.tableView.frame = frame;
    });