I have a non scrolling UITableView
in a UIScrollView
. I set the frame size of the UITableView
to its content size.
When I add a row to the UITableView
, I call insertRowsAtIndexPaths:withRowAnimation
: on the UITableView
. Then I call a method to resize the frame of the UITableView
:
- (void)resizeTableViewFrameHeight { // Table view does not scroll, so its frame height should be equal to its contentSize height CGRect frame = self.tableView.frame; frame.size = self.tableView.contentSize; self.tableView.frame = frame; }
It seems though that the contentSize
hasn't been updated at this point. If I manually calculate the frame in the above method based on the number of rows and sections, then the method works properly.
My question is, how can I get the UITableView
to update its contentSize
? I suppose I could call reloadData
and that would probably do it, but it seems inefficient to reload the entire table when I'm just inserting one cell.
A view that presents data using rows in a single column. iOS 2.0+ iPadOS 2.0+ Mac Catalyst 13.1+ tvOS 9.0+
Set your view controller constraints in the Storyboard and then create an outlet to the UITableView height constraint in your UIViewController subclass (or the constraint that controls the height of the UITableView like the distance to the bottom of the screen).
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"]; }
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