1

In my View Controller's .xib file I'm using a UITableView which has a dynamic number of rows. Because it's not the only element in the .xib file (there are other elements below and above it), I need to change it's height constraint after I know the number of rows. To achieve this, I'm using this solution that works fine.
Therefore:

@implementation MyViewController
{
__weak IBOutlet UITableView *_tableView;
__weak IBOutlet NSLayoutConstraint *_tableViewHeightConstraint;
}

- (void)viewDidAppear:(BOOL)animated
{
 [super viewDidAppear:animated];
 [self adjustHeightOfTableview];
}

- (void)adjustHeightOfTableview
{
 CGFloat height = _tableView.contentSize.height;
_tableViewHeightConstraint.constant = height;
[self.view needsUpdateConstraints];
}

Now this works fine, but the problem is that you can see the height changing when the ViewController is being shown (because of doing this in viewDidAppearof course).
I would like to avoid this and when the ViewController is being shown, it should be shown directly with the needed height.
I've tried calling adjustHeightOfTableview in viewDidLayoutSubviews instead of viewDidAppear as suggested here, but that gives me this error:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after sending -viewDidLayoutSubviews to the view controller. MyViewController's implementation needs to send -layoutSubviews to the view to invoke auto layout.'

I noticed that if I call [self.view layoutSubviews]; at the end of my adjustHeightOfTableview method, then I don't get any error, but my table view is not visible at all. Checking _tableView.contentSize.height with the debugger in viewDidAppear show me that it has the right value. (according to my number of rows)

Calling [self.view layoutIfNeeded]; or [self.view setNeedsLayout]; at the end of my adjustHeightOfTableview method has the same behavior as calling [self.view layoutSubviews]; : no error, but my table view is not visible.

In case it matters, I'm using a custom UITableViewCell.

Does anybody know what am I doing wrong?

Community
  • 1
  • 1
Alex
  • 2,325
  • 3
  • 29
  • 35

1 Answers1

1

Move the code from viewDidAppear: to viewWillAppear:. They are much the same, and valid for much the same sorts of thing, but viewWillAppear: happens out of the user's gaze, which is exactly what you're after. (You'll probably need to call reloadData on the table explicitly first, in order to give it some data.)

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I tried that too, but as mentioned [here](http://stackoverflow.com/questions/20930000/change-height-constraint-programmatically) it doesn't work maybe because the frames of the subviews aren't yet set in the `viewWillAppear` as mentioned [here](http://stackoverflow.com/questions/17637523/view-frame-changes-between-viewwillappear-and-viewdidappear#answer-17637998). When I set a break point and check this line `CGFloat height = _tableView.contentSize.height;` the height is 0. Any other ideas? – Alex May 05 '14 at 03:59
  • 1
    Perhaps the problem is only that you need to call `reloadData` first (in `viewWillAppear:`) so that the table acquires some data. – matt May 05 '14 at 04:11
  • This was the problem! Calling `[_tableView reloadData];` in `viewWillAppear` before adjusting the height constraint solves the problem. Can you please edit your answer so it contains this info too, making it easier for other people to find? Thank you so much! – Alex May 05 '14 at 04:18
  • I'm glad it worked. Doing it in `viewDidLayoutSubviews` should have worked too, however. – matt May 05 '14 at 04:25
  • I don't know why it doesn't. `_tableView.contentSize.height` has the right value, but the table view is not visible. Maybe i'm missing something. Thank you! – Alex May 05 '14 at 04:26