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