I have a tableView I am trying to populate with data. But the data is never loaded. The delegate method numberOfRowsInSection
is called, but cellForRowAt
isn't.
Interface Builder
Simulator Run
XCode Console
View Debugger
Can anyone see what I am doing wrong?
class ChargeDetailsView: UIView {
@IBOutlet weak var chargesTable: UITableView!
@IBOutlet weak var tvSubtotalAmount: UILabel!
@IBOutlet weak var tvDiscountsAmount: UILabel!
@IBOutlet weak var tvTaxesAmount: UILabel!
@IBOutlet weak var tvGrandTotalAmount: UILabel!
private var allCharges:[ServiceLineItem] = []
class func instanceFromNib() -> UIView {
return UINib(nibName: "ChargeDetailsView", bundle: Bundle(for: ChargeDetailsView.self)).instantiate(withOwner: nil, options: nil)[0] as! UIView
}
public override func awakeFromNib() {
super.awakeFromNib()
print("ChargeDetailsView awakeFromNib")
self.chargesTable.delegate = self
self.chargesTable.dataSource = self
self.chargesTable.register(ServiceLineItemCell.nib(), forCellReuseIdentifier: ServiceLineItemCell.identifier)
self.tvSubtotalAmount.text = "-"
self.tvDiscountsAmount.text = "-"
self.tvTaxesAmount.text = "-"
self.tvGrandTotalAmount.text = "-"
}
public func configure(with details: GetReceiptDetails){
self.tvSubtotalAmount.text = "-"
self.tvDiscountsAmount.text = "-"
self.tvTaxesAmount.text = "-"
self.tvGrandTotalAmount.text = "-"
if let priceSubtotal = details.priceSubtotal {
self.tvSubtotalAmount.text = String(format: "$%.02f", Double(priceSubtotal))
}
if let priceDiscount = details.priceDiscount {
self.tvDiscountsAmount.text = String(format: "$%.02f", Double(priceDiscount))
}
if let priceTax = details.priceTax {
self.tvTaxesAmount.text = String(format: "$%.02f", Double(priceTax))
}
if let priceTotal = details.priceTotal {
self.tvGrandTotalAmount.text = String(format: "$%.02f", Double(priceTotal))
}
if details.pricing != nil, let items = details.pricing?.lineItems, items.count > 0 {
allCharges.removeAll()
allCharges.append(contentsOf: items)
print("allCharges total items: \(allCharges.count)")
self.chargesTable.reloadData()
}
}
}
extension ChargeDetailsView: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("ChargeDetailsView numberOfRowsInSection: \(allCharges.count)")
return allCharges.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("row: \(indexPath.row)")
let cell = tableView.dequeueReusableCell(withIdentifier: ServiceLineItemCell.identifier) as! ServiceLineItemCell
cell.configure(with: allCharges[indexPath.row])
return cell
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
Typically, when a table view never asks the data source for cells, it's because the table view has no size. I guess the runtime figures that since the table view has no size, it can't display any cells, so it doesn't need to ask for any.
In this particular case, your table view is inside a vertical stack view. A stack view, in some configurations, depends on the inherent height of its arranged subviews to know how to size them. A label, for instance, has an inherent height (the height
of its intrinsicContentSize
).
But a table view has no inherent height; you have to give it one. Otherwise, the table view's height will be zero — and that's why you don't see it, and why it isn't being asked for cells.
Either you need to apply an absolute height constraint on the table view, or you need to implement the table view's intrinsicContentSize
(or similar) in such a way as to determine the height. The stack view will then take that into account, the table view will have height, the data source will be asked for cells, and you'll start to see something in the table view.