Andre M Andre M - 1 year ago 116
iOS Question

Expand UITableView to show all cells in Stack View?

I am having trouble getting my UITableView to appear full height in my Stack View.

My view tree looks as follows:

- View
- Scroll View
- Stack View
- Table View
- Image View
- Map View

The table view is dynamically populated with data, which works fine. The issue is that only one row is visible at a time and I have to scroll through the list. What I would like to see happen is for the table view to take as much vertical room as it needs to display all the cells.

I did try adjusting table height as follows, but that just ends up with table that no longer scrolls, though even if it did work I would rather have something more dynamic:

override func viewDidAppear(animated: Bool) {
self.detailsTableView.frame.size.height = 200

I am suspecting that it is probably an aspect of the 'stack view' that needs adjusting, but I am not sure at this point. Can anyone suggest an appropriate way?

Answer Source

A UIStackView will compress views wherever it can, to counteract this set a height anchor and width anchor to the UITableView or a priority for its height and width. Here is a working example of how we can be in charge of the dimensions of a table within a stack view.

An extension to instantiate and centrally position the UIStackView

First of all I've written a UIStackView extension so that I don't need to include all the code inside the view controller. Your positioning and setup will be different because you are placing your stack view inside a scroll view, but separating this code out means you can make your own adjustments.

extension UIStackView {

    convenience init(axis:UILayoutConstraintAxis, spacing:CGFloat) {
        self.axis = axis
        self.spacing = spacing
        self.translatesAutoresizingMaskIntoConstraints = false

    func anchorStackView(toView view:UIView, anchorX:NSLayoutXAxisAnchor, equalAnchorX:NSLayoutXAxisAnchor, anchorY:NSLayoutYAxisAnchor, equalAnchorY:NSLayoutYAxisAnchor) {
        anchorX.constraintEqualToAnchor(equalAnchorX).active = true
        anchorY.constraintEqualToAnchor(equalAnchorY).active = true



We don't set a size for the UIStackView only a position, it is the things contained within it that determine its size. Also note the setting of translatesAutoresizingMaskIntoConstraints to false in the UIStackView extension. (It is only required that we set this property for the stack view, its subviews simply inherit the behaviour.)

UITableView class with data source code

Next I've created a basic table class for demo purposes.

class MyTable: UITableView, UITableViewDataSource {
    let data = ["January","February","March","April","May","June","July","August","September","October","November","December"]
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("SauceCell", forIndexPath: indexPath)
        cell.textLabel?.text = data[indexPath.row]
        return cell

Setup of stack view and table in view controller

Finally, the important stuff. As soon as we add our table to the stack view all the frame information is disregarded. So we need the final two lines of code to set the width and height for the table in terms that Auto Layout can understand.

class ViewController: UIViewController {

    override func viewDidLoad() {
        // Do any additional setup after loading the view, typically from a nib.

        let table = MyTable(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height))
        table.registerClass(UITableViewCell.self, forCellReuseIdentifier: "SauceCell")
        table.dataSource = table

        let stack = UIStackView(axis: .Vertical, spacing: 10)
        stack.anchorStackView(toView: view, anchorX: stack.centerXAnchor, equalAnchorX: view.centerXAnchor, anchorY: stack.centerYAnchor, equalAnchorY: view.centerYAnchor)


        table.widthAnchor.constraintEqualToAnchor(view.widthAnchor, multiplier: 1).active = true
        table.heightAnchor.constraintEqualToAnchor(view.heightAnchor, multiplier: 0.5).active = true



Note that we use addArrangedSubview: not addSubview: when adding views to the stack view.

(I've written blogposts about UIStackView as well as others about Auto Layout in general that might help too.)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download