버그 잡이

tableView.reloadData() 이후 스크롤이 튀는 현상 해결방법 #automaticDimension #estimatedRowHeight 본문

IOS

tableView.reloadData() 이후 스크롤이 튀는 현상 해결방법 #automaticDimension #estimatedRowHeight

버그잡이 2020. 12. 7. 21:02

 

tableView를 reload 하는데 스크롤 위치가 조금 아래로 밀려나는 현상이 있었습니다.

원인은 tableView의 cell을 automaticDimension으로 줬기 때문이었습니다.

 

 

automaticDimension 이란?

tableView를 사용할때 cell 마다 높이가 다르게 적용될 수 있습니다.

카카오톡 말풍선만 봐도 글 내용에 따라서 cell 마다 크기가 다릅니다.

그런 경우 아래와 같이 automaticDimension을 적용해주어 rowHeight가 유동적이라고 선언합니다.

 

tableView.rowHeight = UITableView.automaticDimension

 

이 결과 기존의 RowHeight를 무시하고 Row 안의 내용에 따라 Row 높이가 유동적으로 결정되게 합니다.

"Row마다 같은 cell을 사용할지라도 높이가 각각 다를 수 있음을 선언해주는 것" 입니다.

 

 

(바로 이 속성이 스크롤을 엉뚱한 위치로 움직이는 원인이었습니다. 정확한 원인을 알기 위해서 한 가지 개념을 더 살펴보겠습니다.)

 

 

 

estimatedRowHeight

 

말 그대로 예상되는 RowHeight입니다.

automaticDimension을 사용할때는 보통 이 속성을 같이 지정해줍니다.

이 속성을 통해서 대략적인 rowHeight를 미리 알려주는 것입니다.

 

tableView.estimatedRowHeight = 30

 

이 값이 너무 낮으면 tableView가 reloadData 되었을때 엉뚱한 곳에 스크롤 되는 경우가 발생합니다.

즉, 이 값으로 인해서 cell의 높이가 잘못 계산 될 수 있는 것 입니다.

 

 

"그러면 automaticDimension 쓰면서 스크롤은 정확한 위치로 되게 할 수 없는 걸까요?"

 

estimatedRowHeight를 정확한 값으로 넣어주면 문제를 해결할 수 있습니다.

아래와 같은 코드로 cell이 display되기 전에 cell의 height를 받고 이를 estimatedRowHeight로 선언해주는 것입니다.

 

var cellHeights: [IndexPath : CGFloat] = [:]


extension TestViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        cellHeights[indexPath] = cell.frame.size.height
    }
    
    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return cellHeights[indexPath] ?? UITableView.automaticDimension
    }
}

 

 

*참고

 

https://stackoverflow.com/questions/28244475/reloaddata-of-uitableview-with-dynamic-cell-heights-causes-jumpy-scrolling

https://m.blog.naver.com/PostView.nhn?blogId=jdub7138&logNo=220963701224&proxyReferer=https:%2F%2Fwww.google.com%2F

반응형
Comments