Datasource and Traitcollection
Example of accessing the traitCollections within the DataSource. This example illustrates how inheritance can be useful in this situation.
We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
I had this situation where I refactored my UIViewController
so that the UITableViewDataSource
was in a separate file. Below is the example code (shorten for illustration purposes).
class ScheduleTableViewController: UIViewController {
@IBOutlet var tableView: UITableView!
private var dataSource = ScheduleDataSource()
...
}
class ScheduleDataSource: NSObject, UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if traitCollection.preferredContentSizeCategory > .extraExtraLarge {
//...
} else {
//...
}
return cell
}
}
When I had everything in one UIViewController
I had access to traitcollection
. As shown in the screenshot below.
Now that I have my tableView
methods grouped together in a file called ScheduleDataSource
which is a subclass of UITableViewDataSource
I have lost access to the traitCollection
.
This did not make sense initially.
I still needed access to the traitCollection
because I have code that changes the tableView
cell based on the traitCollection.preferredContentSizeCategory
. The code below illustrates what I previously had.
class ScheduleTableViewController: UIViewController {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if traitCollection.preferredContentSizeCategory > .extraExtraLarge {
// Use the cell with one column layout
} else {
// Use the cell with one column layout
}
}
}
Now I had to investigate on how do I get access to that traitCollection
property again? Should I conform to the UITraitEnvironment
or UITraitCollection
protocol?
My initial thinking was to use a protocol. But it turned out the answer was much easier.
The xcode autocomplete screenshot shown earlier in the post tells you the answer. It states that the traitCollection
is available for UIViewControllers
and UIViews
and its subclasses.
The key is its subclasses.
With tableView
it subclasses UIScrolllView
, which subclasses UIView
. This means I should have access to the traitCollection
through the tableView
.
Knowing this you just need to write it out with tableView.traitCollection
, like shown in the example below.
class ScheduleDataSource: NSObject, UITableViewDataSource, UITableViewDelegate {
// ...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView.traitCollection.preferredContentSizeCategory > .extraExtraLarge {
// Use the cell with one column layout
} else {
// Use the cell with two column layout
}
}
}
I didn’t need to conform to any protocol or access the collection through UIScreen.main.traitCollection
. The use of inheritance allowed the solution to be done with minimum effort.