4

I have a 'master' UITableView, in which I use different cells that are loaded from .xib's. Some of these cells themselves also have a UITableView.

For now I have set the row height of each cell to the original xib size. However, I would like to have the height dynamic and corresponding to the amount of rows in the 'child' UITableView.

I run into the following problem:

  • Upon ViewController load, the master UITableView needs to have a height for every cell it has.
  • By the time this height is needed, the child UITableView hasn't loaded its own cells yet, and therefore is not the proper size yet.

I have tried the following:

  • At first, load the cell's with a 'estimated' height
  • The cell loads its own tableView and calls to refresh the master tableView

However, in this case, the cell will use the 'estimated' height to lay out its own rows. Therefore it is always too big or too small.

How do I solve this problem?

knart
  • 311
  • 2
  • 13
  • 1
    Why are you using nested table views? You could have one master UITableView with multiple cell types and have a data model which represents your wanted behaviour. Nested tableViews is always hard to handle... – heyfrank Feb 07 '18 at 15:57
  • But for auto height cells have a look at this link: https://www.raywenderlich.com/129059/self-sizing-table-view-cells – heyfrank Feb 07 '18 at 15:58
  • More than "hard to handle", nested table views are directly recommended against. Any time you have nested views that compete for gesture recognizers, ie table dragging, you have a recipe for UI disaster. No substantially-used app I've ever seen has nested table views. Leverage sectioning and consider alternate ways to display the data. – Connor Neville Feb 07 '18 at 16:06
  • I've used nested TableViews because some sections are better suited in their own xib, as opposed to everything in cells. There is some rather complex animation going on. – knart Feb 07 '18 at 16:17

2 Answers2

13

First Approach:

  1. Create a subclass for child tableView and override intrinsicContentSize.

         class MyOwnTableView: UITableView {
        override var intrinsicContentSize: CGSize {
            self.layoutIfNeeded()
            return self.contentSize
        }
    
        override var contentSize: CGSize {
            didSet{
                self.invalidateIntrinsicContentSize()
            }
        }
    
        override func reloadData() {
            super.reloadData()
            self.invalidateIntrinsicContentSize()
        }
    }
    
  2. In Interface builder change the class of your child tableView to MyOwnTableView (subclass UITableView).

  3. Set automatic row height for both the parent and child table view.

        tableView.estimatedRowHeight = 60.0;
        tableView.rowHeight = UITableViewAutomaticDimension;
    

Second Approach: 1. Create a height constraint with any value for child tableView and conect an IBOutlet that sets the child tableView height. 2. Set the height constraint's constant to tableView.contentSize.height

    self.tableViewHeight.constant = self.tableView.contentSize.height
Learner
  • 1,107
  • 12
  • 14
  • 5
    Where will you set self.tableviewHeight.constant? – jailani Jul 11 '19 at 12:14
  • @Learner I am trying your second approach but I am stuck as I am not able to received the height of innertableviewcell. cell.constraintHeightOfTblView.constant = CGFloat(135 * (cell.arrCourses.count)) – Muju Aug 14 '20 at 05:29
  • The first approach is a more sophisticated one. Just a little thing is missing: call `layoutIfNeeded()` in didSet of "contentSize" property, this will calculate size of cell correctly before displaying it. – Muhammad Umair May 15 '22 at 07:05
2

You could create the object which will create template object of class you want to put in cell, put data in it, calculate its size and return it on sizeForItem method of master tableView. That way you will be able to set returned calculated size for item when master tableView is preparing data.
This is the way i do it in my projects.
You could improve this object with cache, make it generic and use everywhere you may need to.

Sergey Fedorov
  • 199
  • 1
  • 6
  • How can I do it can you share some code. Because I am really stuck my inside tableview cell scrolling deferentially I do not want it to scroll deferentially. – Muju Aug 14 '20 at 05:19