7

After going through all of the other Stack Overflow forms, I have implemented a dynamic height for one of my cells as follows:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell

    if(indexPath.row == 1){
        var image : UIImage = maskRoundedImage(image: UIImage(named: "Temp_Profile.png")!, radius: 150)
        cell.imageView?.image = image
        return cell
    }
    cell.textLabel?.text = TableArray[indexPath.row]
    cell.backgroundColor = UIColor.init(colorLiteralRed: 0.56, green: 0, blue: 0.035, alpha: 1)
    cell.textLabel?.textColor = UIColor.white
    cell.textLabel?.font = UIFont(name: "Helvetica", size: 28)

    return cell
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    if  indexPath.row == 1 {
        return UITableViewAutomaticDimension * 3

    }
    return UITableViewAutomaticDimension
}

It seems pretty straightforward, but a debugging session is showing that heightForRowAtIndexPath is never being called. The View Controller is a UITableViewController and everything else works properly. Do any of you see any reason that this function is not being called?

Thank you for the help!

Code Wiget
  • 1,540
  • 1
  • 23
  • 35
  • As mentioned below, UITableViewAutomaticDimension is not a value that should be used for arithmetic. returning UITableViewAutomaticDimension * 3 will have unpredictable effects. – GetSwifty Feb 02 '17 at 16:18
  • Note that calling `heightForRowAt` can be expensive; you could also call `self.tableView.rowHeight = UITableViewAutomaticDimension` and `self.tableView.estimatedRowHeight = 72.0 //estimated, average value` in `viewDidLoad`. Se also eg here: https://www.appcoda.com/self-sizing-cells/ – koen Feb 02 '17 at 16:22

4 Answers4

18

In Swift 3, the signature is:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat

You have the old signature so it isn't recognized.

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if indexPath.row == 1 {
        return UITableViewAutomaticDimension * 3

    }
    return UITableViewAutomaticDimension
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • 3
    For anyone who attempted to use UITableViewAutomaticDimension * 3, don't . It returns a -1 as just a signal to the tableView to make it default. Use an actual number – Code Wiget Feb 02 '17 at 16:11
  • 1
    It's very easy to end up with the old signatures for these methods when you're copying examples from elsewhere - as we all do!. In some cases, XCode will generate an error if Swift has moved on enough to make things invalid - but for cases like this you only get a warning. That's you shouldn't ignore those yellow triangles. Auto-complete should give you the correct signature, and then the rest of the function will most likely be OK. – Russell Feb 02 '17 at 16:42
16

For me, I had to do this.

self.tableviewObj.delegate = self

So, don't forget to add delegate to self. Because heightForRowAtIndexparth is declared in delegate protocol.

Narasimha Nallamsetty
  • 1,215
  • 14
  • 16
1

In my case, I have three controller A, B, C. A is base controller, B inherits from A, and C inherits from B. I set tableView delegate in A, and implement heightForRowAt function in B, and the problem occurred when i use C. I guess because the proxy assigned in A eventually points to C, so the method in B is not called.

nullLululi
  • 194
  • 1
  • 7
  • If you have a NEW question, please ask it by clicking the [Ask Question](//stackoverflow.com/questions/ask) button. If you have sufficient reputation, [you may upvote](//stackoverflow.com/privileges/vote-up) the question. Alternatively, "star" it as a favorite and you will be notified of any new answers. – Johan Apr 30 '19 at 08:17
  • In that case, (me too), and I found the solution was to define a placeholder method call in the base class and then override it in the descendants. Then it gets called. – Paul Stevenson Jan 28 '20 at 05:11
0

if you are inside a UITableViewController, just remember that the method has to be one that you need to override or the method name is wrong.

In my case I had NSIndexPath instead of IndexPath and it didn't match to the right method to be called

tableView(_ tableView: UITableView, heightForRowAt indexPath: NSIndexPath) -> CGFloat

when I corrected it to

tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat

xcode would prompt for insertion of the override keyword.

Archy Will He 何魏奇
  • 9,589
  • 4
  • 34
  • 50