Im quite new to iOS development and i've been stuck with this for a couple of days
i have a UITableView
and UIImageView
inside a UIScrollView
, the UIImageView
is on top of the table and the height is static so i don't have any issues with that, the problem is the UITableView
, i need to get the height dynamically based on the content and set that height to a height constraint of the table and the contentsize of the scrollview.
The cells are self sizing, so the height of the cell varies depending on the content. The best i could do so far is getting the height by using contentSize.height
property of UITableView
but apparently this returns a height based on the estimatedRowHeight
i set, not te actual height of each row.
the code:
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.estimatedRowHeight = rowHeight
tableView.rowHeight = UITableViewAutomaticDimension
tableView.layoutIfNeeded()
tableHeight.constant = tableView.contentSize.height
scrollView.contentSize.height = imageView.bounds.height + tableView.contentSize.height
}
What i've tried:
- Getting the height by using
contentSize.height
property of UITableView
, as shown in the code and explained before.
Getting the height of each row individually on willDisplayCell
and add it to the height constraint of the table and the contentSize of the scrollview. But looks like this adds more rows than actually are, giving me a bunch of empty cells at the end of the table. the code inside willDisplayCell
:
let cellHeight = cell.bounds.height
tableHeight.constant += cellHeight
scrollView.contentSize.height += cellHeight
The same as before, except i tried inside cellForRowAtIndexPath
with the same result.
The Apple documentation discourages embedding UITableView
within a UIScrollView
:
You should not embed UIWebView or UITableView objects in UIScrollView objects. If you do so, unexpected behavior can result because touch events for the two objects can be mixed up and wrongly handled.
To solve your problem, you could put the UIImageView in a header view, or change the cell of your first row to display an image. You would then adjust the cell heights using your UITableViewDelegate
, specifically tableView:heightForRowAtIndexPath:
.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// adjust the return based on the indexPath
return 30;
}
i had the same problem and i found a solution. I have a TableView inside of UIScrollView and didn't know how to set dynamically height of UIScrollView. First of all u have to set up your scrollView, u can check it here in stackOverFlow (How to use UIScrollView in Storyboard). The next step is to set tableView's constraints to scrollView(it should be tableView's superView): leading,trailing and bottom (bottom is 0 and others whichever u want), and the top constraint to the closest object with constant whichever you want.
So now you have to set dynamically height of UIScrollView. It depends on 2 things: your device screen's height and tableView's height (because tableView's content is dynamically).
You have to use this extension to make device determination more comfortable: iOS: How to determine the current iPhone/device model in Swift?
After those things i did this:
var viewHeight: CGFloat = 0
var modelDevice: String {
get {
return UIDevice.currentDevice().modelName
}
}
var tableViewHeight: CGFloat {
get {
// 90 is my tableViewCell's row height
return CGFloat(detail.cart.count) * 90
}
}
func configureSelfHeight(modelDevice: String) {
switch modelDevice {
case "iPhone 4", "iPhone 4s": viewHeight = 480
case "iPhone 5", "iPhone 5c", "iPhone 5s", "iPhone SE": viewHeight = 568
case "iPhone 6", "iPhone 6s", "iPhone 7": viewHeight = 667
case "iPhone 6 Plus", "iPhone 6s Plus", "iPhone 7 Plus": viewHeight = 736
default: viewHeight = 568
}
scrollView.contentSize.height = viewHeight + tableViewHeight
}
and just call this method inside of viewDidLayoutSubviews():
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
configureSelfHeight(modelDevice)
}
I hope it will help you.:)