When does a UITableView's contentSize get set?
You can make the UITableView calculate the size of the content immediately by calling layoutIfNeeded
on the UITableView
. This will run all the necessary calculations to layout the UITableView
.
Example for a UITableViewController
subclass that you want to put in a container view with variable size:
Objective-C
- (CGSize)preferredContentSize
{
// Force the table view to calculate its height
[self.tableView layoutIfNeeded];
return self.tableView.contentSize;
}
Swift
override var preferredContentSize: CGSize {
get {
// Force the table view to calculate its height
self.tableView.layoutIfNeeded()
return self.tableView.contentSize
}
set {}
}
While I don't love KVO (Key-Value Observing), it's a fairly good way to know exactly when your table's contentSize
has changed (rather than just calling your update methods in a bunch of random places). It's rather simple to use (though somewhat cryptic and implicit). To observe changes on your table's contentSize
, do the following:
1) Become an observer of your table's contentSize
property like so:
[self.tableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:NULL];
This is usually done in the view controller that holds the tableView
(like in viewDidLoad:
, for example).
2) Implement the KVO observing method and make the changes you need:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
if(object == self.tableView && [keyPath isEqualToString:@"contentSize"]) {
// perform your updates here
}
}
3) Remove your view controller as an observer at some logical point (I call it in dealloc
). You do this like so:
- (void)dealloc {
[self.tableView removeObserver:self forKeyPath:@"contentSize"];
}
Try this:
- (void)resizeTableViewFrameHeight
{
UITableView *tableView = self.tableView;
CGRect frame = tableView.frame;
frame.size.height = [tableView sizeThatFits:CGSizeMake(frame.size.width, HUGE_VALF)].height;
tableView.frame = frame;
}