Swift 5 and 4.2 solution without KVO, DispatchQueue, or setting constraints yourself.
This solution is based on Gulz's answer.
1) Create a subclass of 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) Add a UITableView to your layout and set constraints on all sides. Set the class of it to ContentSizedTableView.
3) You should see some errors, because Storyboard doesn't take our subclass' intrinsicContentSize into account. Fix this by opening the size inspector and overriding the intrinsicContentSize to a placeholder value. This is an override for design time. At runtime it will use the override in our ContentSizedTableView class
Update: Changed code for Swift 4.2. If you're using a prior version, use UIViewNoIntrinsicMetric instead of UIView.noIntrinsicMetric
Actually I found the answer myself.
I just create a new CGRect for the tableView.frame with the height of table.contentSize.height
That sets the height of the UITableView to the height of its content.
Since the code modifies the UI, do not forget to run it in the main thread:
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;
});
Swift Solution
Follow these steps:
Set the height constraint for the table from the storyboard.
Drag the height constraint from the storyboard and create @IBOutlet for it in the view controller file.
@IBOutlet var tableHeight: NSLayoutConstraint!
Then you can change the height for the table dynamicaly using this code:
override func viewWillLayoutSubviews() {
super.updateViewConstraints()
self.tableHeight?.constant = self.table.contentSize.height
}
If the last row is cut off, try to call viewWillLayoutSubviews() in willDisplay cell function:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
self.viewWillLayoutSubviews()
}
I've tried this in iOS 7 and it worked for me
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView sizeToFit];
}
Add an observer for the contentSize property on the table view, and adjust the frame size accordingly
[your_tableview addObserver:self forKeyPath:@"contentSize" options:0 context:NULL];
then in the callback:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
CGRect frame = your_tableview.frame;
frame.size = your_tableview.contentSize;
your_tableview.frame = frame;
}
Hope this will help you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With