UITableView is a most important thing which as a developer for iOS in UIKit you will be most likely be used in almost every instance where you want to show a list of elements in order and it is simple to understand but sometimes there are some situations where the requirement is that you want a tableView inside a tableView and you want to show the data dynamically so most of the times especially beginners are confused about this and they are not able to identify how they can achieve this, how will they set the height of that table which is inside and how dynamically the height of the tables can be set that can help us achieve our goal so here we at Qurious Click will show you the easiest way to achieve this thing.
let arrOuterData = ["1st century BCE",
"2nd century BCE",
"3nd century BCE",
]
let arrInnerData = [
["The practice of acupuncture is described in Nei Qing, a Chinese medical text"
,"Sulla, campaigning to the east, besieges Athens and then allows his army to loot the city"],
["Cement is in use for construction in Asia Minor, possibly developed first in Pergamum"],
["Phoenicia is brought into the new Hellenistic empire, changing hands frequently between contending successors of Alexander"
,"Pyrrhus lands in Italy, with 25,000 men and 20 elephants, to fight for the Greek colony of Tarentum against the Romans",
"The Jewish community of Alexandria coins the word diaspora for Jews living far from Israel"]
]
So here we have an outer array and corresponding data of that century is in an inner array so we will try to create this in a tableView where we will show all outer array data on the first table and the inner array of String on the second TableView which is inside first TableView and it will be having dynamic height and according to the number of elements we have our tableView’s hight will be changed so let’s see how we can achieve it.
@IBOutlet weak var innerTableView:UITableView!
@IBOutlet weak var outerTableView:UITableView!
For naming convention, the tableView which shows the keys is called ‘outerTableView’, and the tableView which is inside the first table view is called ‘innderTableView’.
Here we have a tableView and inside that there is a tableView and every element has an outlet inside our main and tableView’s file (this tutorial is not made for neophytes so that we have skipped how we made this tableView inside a tableView in storyBoard you can find many tutorials for that on the internet)
Now we will pass the data to our outerTableView data Source and then from there to innerTableView without our trick (when I was a beginner, I used to do like this and then just give a fixed height to tableView so that it looks good) but don’t worry I will make sure you don’t make that mistake that I made so let’s see how it looks with old me.
So what we have here we can’t even see the second tableView what is going on! now if you are making it for the first time you will be super confused and probably you will delete this app and start again (I used to do that) who will find what has gone wrong let’s start again but we will not do that because the problem is simple and can easily be solved and here comes our solution just create a new file which is a subclass of UITableView and in storyBoard assign the innerTableView to this class.
class myTableView: UITableView {
}
Now we will override variables and a function inside our newly created subClass of UITableView like this
import UIKit
class myTableView: UITableView {
override var intrinsicContentSize: CGSize {
self.layoutIfNeeded()
return self.contentSize
}
override var contentSize: CGSize {
didSet{
self.invalidateIntrinsicContentSize()
}
}
override func reloadData() {
super.reloadData()
self.invalidateIntrinsicContentSize()
}
}
- Intrinsic content size: so this is the natural size of our content so what we are doing here is whenever this variable is initialized we are calling layout if needed so what it will do is it will calculate the height of the particular cell again and we will get its height according to what content size it has but what happened is if the table is reloaded then its size is not gone down again and so we get the results which we are not expecting so what to do? Don’t worry we have another solution for that
- Contents and reloadData: whenever the size of the content is measured again and data is getting reloaded, we are calling ‘invalidateIntrinsicContentSize’ so that when our ‘intrinsicContentSize’ variable is initialized we can get the contents accurately.
But still, there is a problem the tableView needs to know an estimated height of the cells but if we give that our cells will not be dynamic so to eat both sides of a cake, we will give automatic dimension to the weight of our innerTableView like this
override func awakeFromNib() {
super.awakeFromNib()
innerTableView.dataSource = self
innerTableView.delegate = self
innerTableView.estimatedRowHeight = 120
innerTableView.rowHeight = UITableView.automaticDimension
}
So now when we run the app, we have our tableView which is getting dynamic height accordant to its content.