UITableView scrollToRowAtIndexPath scrolls to wrong offset with estimatedRowHeight on iOS 7

后端 未结 9 1889
轮回少年
轮回少年 2021-02-12 12:46

I am using the estimatedRowHeight method from UITableView in iOS 7, which works perfectly for fast loading of a UITableView with 5000 rows of variable heights.

9条回答
  •  你的背包
    2021-02-12 13:22

    When scrollToRowAtIndexPath is called, height of all the cells b/w current position and target offset are not calculated. Only some of them are.

    Instead, UITableView uses estimatedRowHeight to calculate target offset which leads to wrong offset.

    I'm facing the same issue and I found a small trick(which I don't really like) to calculate exact cell height only once after initial relaodData. I inserted two lines below:

    tableView.reloadData()
    
    // only for the initial reloadData
    
    let numSections = tableView.numberOfSections
    let numRowsInLastSection = tableView.numberOfRowsInSection(numSections-1)
    
    // scrolls to the last row in the tableView
    tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: numRows-1, inSection: numSections-1), atScrollPosition: .Bottom, animated: false)
    
    // back again to the original position(which is 0 for this is only called right after the initial reloadData)
    tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: .Top, animated: false)
    

    This results in the tableView appearing on the screen late, but I think it's acceptable rather than freezing UI after the tableView appeared. It's even better when you call an API on the beginning because it feels like a little delay on the network, not the UI lag.

    After this, tableView jumps to exact position of the cells.

    Yeah, I don't really like this solution either :|

    EDIT:

    The only reason I did this was to calculate actual row height by calling cellForRowAtIndexPath:, but I found out when giving proper estimatedHeight for every row by delegate method estimatedHeightForRowAtIndexPath: instead of giving static value to UITableView.estimatedRowHeight solves the issue.

    What I finally did was to cache the heights of rows from willDisplayCell:forRowAtIndexPath: to disk and use that value on estimatedHeightForRowAtIndexPath:.

    By doing this, estimatedHeightForRowAtIndexPath: for all rows are called in the beginning and scrollToRowAtIndexPath works well.

提交回复
热议问题