0

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

enter image description here

Simulator Run

enter image description here

XCode Console

enter image description here

View Debugger

enter image description here

enter image description here

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
    }
}
user-44651
  • 3,924
  • 6
  • 41
  • 87
  • 1
    you have to give height constraint to tableview – Pratik Prajapati Oct 01 '20 at 15:27
  • Are you sure your table view has size? My experience is that `cellForRowAt` not being called is usually because the table view has zero size. Run the app and use the View Debugger to check; it will show you that immediately. – matt Oct 01 '20 at 15:27
  • @matt the view shows that the table is empty. I updated the question with a screen shot of the debugger. – user-44651 Oct 01 '20 at 15:33
  • Having selected the table view like that, look over at the other side of the project window at the size inspector and see if it has size. – matt Oct 01 '20 at 15:35
  • @matt it doesn't look like it has a height. I updated the question with the screenshot. The tableView is inside a StackView. – user-44651 Oct 01 '20 at 15:39
  • Yup, perfect, that's the problem (as Pratik Prajapati said right at the start). Excellent! – matt Oct 01 '20 at 15:41
  • @matt how am I suppose to do that? The tableview is in a uistackview. The tableview will have x number of items. The StackView resizes all the views to Fill – user-44651 Oct 01 '20 at 15:43
  • 1
    Well, a table view has no magic inherent height. It's up to _you_ to decide what its height needs to be, and specify that. That's been discussed many times here, so do a search. This might be a good starting place: https://stackoverflow.com/questions/44852663/dynamic-height-of-uitableview – matt Oct 01 '20 at 15:52
  • No problem, I'll give it as an answer. – matt Oct 01 '20 at 15:59

1 Answers1

3

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.

matt
  • 515,959
  • 87
  • 875
  • 1,141