5

So I have a tableView where I want to change the height of a cell when tapped. Well, actually, I am replacing it with a bigger cell. On tap, I call:

tableView.beginUpdates()
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
tableView.endUpdate()

And then I modify my cellForRowAtIndexPath to return the right new cell and height. The cell's height is being automatically calculated by overriding sizeThatFits in the cell's implementation:

override func sizeThatFits(size: CGSize) -> CGSize {
    return CGSizeMake(size.width, myHeight)
}

Oddly enough, after I do this, scrolling downwards is fine, but when I scroll upwards, the table jumps 5 or so pixels every second until I reach the top. After I reach the top of the table, the problem is gone and there is no jumping going in either direction. Any idea why this is happening? I imagine it has something to do with the new cell height displacing the other cells, but I can't see why the tableView is not taking care of this. Any help is appreciated!

Thanks!

EDIT: Added code from cellForRowAtIndexPath:

 if self.openedCellIndex != nil && self.openedCellIndex == indexPath {
     cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as ListCell
     (cell as ListCell).updateWithDetailView(dayViewController!.view)
 } else {
     cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as ListCell
     (cell as ListCell).updateWithData(eventDay: store.events![indexPath.row], reminderDay: store.reminders![indexPath.row])
 }
 return cell
Kyle Rosenbluth
  • 1,672
  • 4
  • 22
  • 38
  • Have you solved this? I'm having the same issue and can't get to the bottom of it. – David Jan 30 '15 at 12:16
  • @David my fix was to unfortunately stop using the automatic cell sizing and go back to the old `heightForRowAtIndexPath`. – Kyle Rosenbluth Jan 31 '15 at 03:00
  • I too have come to the conclusion that I need to do that, but I've been having trouble figuring out how to calculate the height of the cell. Do you happen to have a reference to how you went about it? – David Jan 31 '15 at 03:18

3 Answers3

0

You should include your code for cellForRow and heightForRow, but I will give it a blind shot.

When a cell is tapped in cellForRow you should store the index of that cell, then reload the data or just that cell. Then in heightForRow use if(yourTappedCell){return preferredHeight;}

Community
  • 1
  • 1
TheSD
  • 873
  • 5
  • 17
  • Thanks TheSD, I'll add those to methods in an edit. But I am already doing what you mentioned. Both of those methods properly handle the new cell height. In fact, it looks like it works perfectly before scrolling, it is only when you scroll up that the jumping appears. – Kyle Rosenbluth Oct 22 '14 at 23:02
0

Unfortunately, there does not seem to be a simple answer to this. I have struggled with it on multiple iOS apps.

The only solution I have found is to programmatically scroll to the top of your UITableView once it appears again.

[self.tableView setContentOffset:CGPointMake(0, 0 - self.tableView.contentInset.top) animated:YES];

OR

self.tableView.contentOffset = CGPointMake(0, 0 - self.tableView.contentInset.top);

Hope this an acceptable work around while still being able to use dynamic cell heights =)

BennyTheNerd
  • 3,930
  • 1
  • 21
  • 16
0
func refreshCellState(indexPath:IndexPath) {
    
    guard let cell = tableView.cellForRow(at: indexPath) as? ListCell else {
        return
    }
    
    if self.openedCellIndex != nil && self.openedCellIndex == indexPath {
        cell.updateWithDetailView(dayViewController!.view)
    } else {
        cell.updateWithData(eventDay: store.events![indexPath.row], reminderDay: store.reminders![indexPath.row])
    }
    
    self.tableView.beginUpdates()
    self.tableView.endUpdates()
    
    if #available(iOS 11.0, *) {
        self.tableView.performBatchUpdates {
            
        } completion: { complete in
            if complete {
                self.tableView.scrollToRow(at: indexPath, at: .none, animated: true)
            }
        }
    } else {
        // Fallback on earlier versions
        self.tableView.reloadData()
    }
}

Here, Dont reload that cell entirely, But take that cell when clicked and provide data to cell from there. Now call begin and endUpdated methods of tableview to update height.