I encountered with a problem when was trying to build a table view inside a cell of another table view. I thought it’s pretty straightforward task...
Structure of app:
- Collection view with workout items.
- After tapping on each, user will be moved to static table view, where problem’s occurred.
I noticed in Reveal app that table view appears in the cell and it doesn’t shout that constraints are not correct, everything seems fine. But table view has height of its frame 0.333.
Reveal app screenshot and the fact that table view exists
But user would see this:
I tried methods(with different values) as tough: estimatedHeightForRowAt
, heightForRowAt
, but they do nothing, by the way UITableView.automaticDimension
returns -1.
But when I set explicitly height for the row for outermost table view everything is good, except the fact that the size will be different in distinct elements, and table view is too big, or too small. I made this constraint, but it seems work only for one case when element has 3 splits:
self.heightAnchor.constraint(equalToConstant: 40 titleLabel.frame.height CGFloat(splits.count) * 44.0)
With 3 splits in element | Less than 3 |
---|---|
I read that adding subviews of custom cell to contentView instead of cell itself helped somebody, but in my case I got this message:
Warning once only: Detected a case where constraints ambiguously suggest a height of zero for a table view cell's content view. We're considering the collapse unintentional and using standard height instead. Cell: <projectClimber.SplitCell: 0x140670050; baseClass = UITableViewCell; frame = (0 0; 355 44); autoresize = W; layer = <CALayer: 0x600003797700>>
I was able to dispose of this warning actually by removing contentView and just add sub view to cell itself. But it doesn’t solve anything.
I don’t really know how to set proper value to table view's height, maybe there’s an approach without using table view or maybe in different way. I want to hear your opinion about this, thank you.
Code
Main table view
class WorkoutStatisticsTableViewController: UITableViewController {
....
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//...
//Switch statement and other cases
//...
case 3:
let cell = FourthTableViewCell()
cell.configure(with: workout)
cell.selectionStyle = .none
// Here I added
return cell
}
//I tried these methods, but nothing changed
// override func tableView(_ tableView: UITableView, estimatedHeightForRowAt
indexPath: IndexPath) -> CGFloat {
// return 250
// }
//
// override func tableView(_ tableView: UITableView, heightForRowAt indexPath:
IndexPath) -> CGFloat {
//
// return UITableView.automaticDimension
// }
....
}
Table view cell class, where lay title label and table view
class FourthTableViewCell: UITableViewCell, UITableViewDelegate, UITableViewDataSource {
//...
//Methods for tableview delegate and data source and implementation of title label
//...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: SplitCell.reuseIdentifier, for: indexPath) as! SplitCell
cell.configure(cellWithNumber: indexPath.row 1, with: splits[indexPath.row])
cell.selectionStyle = .none
return cell
}
//Number of splits, i.e. rows in table view in this cell
var splits: [Int] = []
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
self.tableView.dataSource = self
self.tableView.delegate = self
//just for making table view visible
self.tableView.backgroundColor = .orange
tableView.register(SplitCell.self, forCellReuseIdentifier: SplitCell.reuseIdentifier)
addSubview(titleLabel)
addSubview(tableView)
titleLabel.translatesAutoresizingMaskIntoConstraints = false
tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
titleLabel.topAnchor.constraint(equalTo: topAnchor, constant: 20),
titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20),
titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20),
tableView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 10),
tableView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 10),
tableView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10),
tableView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -10),
// Tried this line for calculating height of cell
// self.heightAnchor.constraint(equalToConstant: 40 titleLabel.frame.height CGFloat(splits.count) * 44.0)
])
}
//Configure cell with workout element, which is used for taking splits
func configure(with workout: Workout) {
print("Configure func, workout's splits \(workout.splits.count)")
//Need to populate splits this way, because in workout I use List<Int>
for item in workout.splits {
self.splits.append(item)
}
}
}
Split cell class. Where is located only two labels
class SplitCell: UITableViewCell {
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
addSubview(titleLabel)
addSubview(timeLabel)
titleLabel.translatesAutoresizingMaskIntoConstraints = false
timeLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
titleLabel.topAnchor.constraint(equalTo: topAnchor, constant: 10),
titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 15),
titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -10),
timeLabel.topAnchor.constraint(equalTo: topAnchor, constant: 10),
timeLabel.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 50),
timeLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -10)
])
}
func configure(cellWithNumber number: Int, with time: Int) {
titleLabel.text = "Split #\(number)"
timeLabel.text = String.makeTimeString(seconds: time)
}
}
CodePudding user response:
After dozen of tries I decided to use this constraint for table view, that is located inside a cell of static table view:
tableView.heightAnchor.constraint(equalToConstant: CGFloat(splits.count) * 27)
But there's still a problem - magic value. 27 is a sum of 17, which is a height of label and 10 is a sum of constant of bottom and top constraints of label in an inner table view's cell.
I'm convinced there's a better solution somewhere, but for now it's better than nothing.