Darren Darren - 4 months ago 82
iOS Question

When does a UITableView's contentSize get set?

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.

Answer

You can force the UITableView to calculate the size of the content by calling layoutIfNeeded on the UITableView.

Example for a UITableViewController subclass that should be in a container view with variable size:

- (CGSize)preferredContentSize
{
    // Force the table view to calculate its height
    [self.tableView layoutIfNeeded];
    return self.tableView.contentSize;
}

Update 2016-07-28 This is an untested Swift example of the same thing. It should work but if it doesn't please leave a comment. There might be nicer or more idiomatic ways to do this. Unfortunately I am not very familiar with Swift.

override var preferredContentSize: CGSize {
    get {
        self.tableView.layoutIfNeeded()
        return self.tableView.contentSize
    }
    set {}
}