Swift + iOS/iOS

[ios] Self-Sizing Table View Cells

군옥수수수 2018. 6. 5. 21:36

[ios] Self-Sizing Table View Cells


안녕하세요. 오늘은 테이블 뷰의 셀의 크기를 동적으로 관리하는 방법에 대해 알아보는 시간을 갖도록 하겠습니다. 기본적으로 UITableViewCell 의 높이는 UITableViewDelegate 프로토콜 메소드에 의해 정해집니다.


  • tableView(_:heightForRowAt:)

하지만 셀의 높이는 항상 같을 수는 없습니다. 예를 들어 메신저 앱의 채팅 방의 대화 내역을 테이블 뷰로 구현한다면 각 셀의 높이는 사용자가 입력한 글자 수에 따라 달라질 것입니다.


그렇기 때문에 위와 같이 셀의 높이를 동적으로 관리하기 위해서는 tableView(_:heightForRowAt:) 메소드로는 충분하지 않습니다.

이를 구현하기 위해 테이블 뷰의 다음 두 가지 프로퍼티를 사용합니다.


  • tableView.rowHeight
  • tableView.estimatedRowHeight

먼저 간단히 설명해드리자면 .rowHeight에는 UITableViewAutomaticDimension 값을 할당할 것입니다. 즉 컨텐츠에 맞게 자동으로 높이를 계산해서 반환한다는 의미입니다.


.estimatedRowHeight는 직역하자면 어림잡아 계산한 셀의 높이를 의미합니다. 물론 이곳에 0 이상의 아무 값이나 입력해도 셀의 높이는 우리가 원하는대로 나옵니다. 하지만 실제 계산되어 반환되는 동적인 셀의 높이 값과 .estimatedRowHeight로 지정해준 값의 차이가 많이나면 퍼포먼스의 차이가 나타나는 것 같습니다. 문서에서는 이를 다음과 같이 설명합니다.


Providing a nonnegative estimate of the height of rows can improve the performance of loading the table view. If the table contains variable height rows, it might be expensive to calculate all their heights when the table loads. Using estimation allows you to defer some of the cost of geometry calculation from load time to scrolling time.

이 두 프로퍼티를 사용하는 것 이외에도 셀 안에서 컨텐츠들의 Auto Layout을 어떻게 지정해주느냐도 굉장히 중요합니다. 셀 안의 컨텐츠들의 Constraint는 그들로 인해 직접적이든, 추론적이든 높이의 값이 확실히 계산이 되어야 한다는 것입니다. 이를 문서에서는 다음과 같이 표현하고 있습니다.


Next, lay out the table view cell’s content within the cell’s content view. To define the cell’s height, you need an unbroken chain of constraints and views (with defined heights) to fill the area between the content view’s top edge and its bottom edge. If your views have intrinsic content heights, the system uses those values. If not, you must add the appropriate height constraints, either to the views or to the content view itself.

제가 자꾸 문서의 내용을 언급하는 것은 번역을 하여 설명하는 것보다 원문 그대로 보는 것이 때로는 더욱 이해가 잘되기 때문이고 이번 포스팅이 그에 해당하는 것 같기 때문입니다.


먼저 두 개의 UILabel이 셀의 컨텐츠로 들어가는 예제를 살펴보도록 하겠습니다. 제가 원하는 결과물은 다음과 같습니다.



저는 두 UILabel의 Constraint를 다음과 같이 설정하였습니다.


  • 첫 번째 UILabel의 Top, Leading, Trailing Constraint의 constant를 셀의 8로 Superview에 대해 Equal로 지정합니다. 그리고 여기서 중요한 것은 첫 번째 UILabel은 글자의 수가 많고 이는 여러 줄이 될 수 있기 때문에 Attributes Inspector의 Lines 속성 값을 0으로 지정해주어야 합니다.
  • 두 번째 UILabel은 SuperView 내에서 바닥에 붙여놓을 것이기 때문에 Bottom, Leading, Trailing의 constant 값을 8로 그리고 SuperView에 대해 Equal로 지정합니다.
  • 아직 끝나지 않았습니다. 이 두 UILabel간에는 간격이 존재해야하기 때문에 Vertical Space Constraint를 지정해주는데 여기서 Equal로 지정해주면 에러가 발생합니다. 왜냐하면 둘의 Vertical Hugging Priority가 같기 때문입니다. 이를 해결하기 위해서는 여러가지 방법이 존재합니다. 두 번째 UILabel의 Vertical Hugging Priority의 값을 첫 번째 UILabel의 것보다 크게 지정해주거나 둘 사이의 Vertical Space Constraint의 관게가 Equal이 아닌 Greater Than Equal로 지정해주어야 합니다.

이렇게 지정하면 원하는 결과를 확인하실 수 있으실 겁니다.


이번에는 UILabel 이 아닌 이미지를 갖는 셀을 이미지의 사이즈와 비율에 대해 동적인 높이를 갖도록 설정해보도록 하겠습니다. 이는 사실 위의 예제보다 더욱 간단합니다. 제가 원하는 결과물은 다음과 같습니다.



두 셀의 높이가 다른 것을 확인할 수 있죠?

저는 셀안의 UIImageView를 다음과 같이 배치하였습니다.


UIimageView 뿐만아니라 셀안의 컨텐츠들을 이렇게 Top과 Bottom에 대해 확실히 지정을 해준다면 셀의 높이는 컨텐츠들의 값에 의해 동적으로 결정될 것입니다.


마무리

오늘은 이렇게 UITableViewCell 의 높이를 동적으로 관리하는 방법에 대해 알아보았습니다. Auto Layout에 대해서는 어느정도 익숙하셔야 해당 내용을 학습하는데 도움이 될 것 같습니다. 감사합니다.


참고자료


  1. Working with Self-Sizing Table View Cells
  2. Raywenderlich - Self-Sizing Table View Cells