일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- SwiftGen
- 2018 KAKAO BLIND RECRUITMENT
- parse
- 정보처리기사 실기 요약본
- cocoapods
- issecuretextentry
- JSONParser
- programmers
- 티스토리챌린지
- JSON
- Pod
- 정보처리기사
- UITableView
- swift
- RealmSwift
- Codable
- storybaord
- JSONSerialization
- 정보처리기사 실기
- 위클리챌린지
- Decodable
- PageViewController
- CustomCode
- 프로그래머스
- dynamic height
- pbxfilesystemsynchronizedrootgroup
- IOS
- pbxgroup
- Custom PageViewController
- Xcode
- Today
- Total
iOS 개발일기
[Swift] UITableView Dynamic Height 본문
기존에는 동적 높이를 할당할 때에 모든 UI 요소들에 제약조건을 모두 상위 뷰에 맞춰 크기가 같이 커지도록 설정된 셀만 사용했었으나,
이번 프로젝트에서 각각의 셀은 동적인 높이를 가지지만 UI 요소 중 타이틀과 버튼의 크기는 고정 크기를 가지고 유지되면서 중앙의 UILabel만 높이가 동적으로 변하도록 구성해야 됐다.
AutoLayout 기반으로 UI를 코드로 작성하면서 높이를 지정해주는 상황이 적다보니 생소한 부분이기도 했고
단순하게 셀의 높이를 `UITableView.automaticDimension` 으로 설정한 후에 셀 내에 타이틀과 버튼에 최소 크기를 명시해주기만 하면 속성에서 자동으로 최소 크기를 따라가지 않을까? 라는 생각에 타이틀과 버튼에 최소 크기를 지정한 결과...
셀 내에 Frame을 가지는 UI 요소의 높이가 `UITableView.automaticDimension`속성의 높이가 결정되는 대에 영향을 미치지 않는구나라는 것을 알게 되었다.
(`extimatedRowHeight`도 마찬가지로 테이블 뷰가 아직 높이를 계산하지 않은 셀의 높이를 추정하기 위해 사용되는 값일 뿐, 최소 값에 직접적인 영향을 미치진 않는다.)
이렇게 저렇게 해결 방법이 몇 가지 존재하였으나 서칭하던 중
`systemLayoutSizeFitting(_:widthHorizontalFittingPriority:verticalFittingPriority:)` 라는 메서드의 존재에 대해 알게 되었는데 해당 메서드는 제약조건과 지정된 우선순위에 따라 최적의 View 크기를 반환하는 메서드라고 되어있다.
따라서, 제약조건이 설정되었을 때 즉 automaticDimension을 통해 셀의 크기가 결정되는 시점에 호출되는 메서드인 것이다.
이 메서드를 잘 이용하면 셀의 최소 크기도 지정할 수 있겠다 생각했다.
뷰 컨트롤러에서는 테이블 뷰 셀의 크기를 동적으로 할당될 수 있도록 지정해주고
func tableView(
_ tableView: UITableView,
cellForRowAt indexPath: IndexPath
) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(
withIdentifier: "DynamicCellID",
for: indexPath
) as! DynamicCell
cell.configure(datas[indexPath.row])
return cell
}
func tableView(
_ tableView: UITableView,
heightForRowAt indexPath: IndexPath
) -> CGFloat {
return UITableView.automaticDimension
}
셀 내에서는 동적으로 크기가 할당되는 시점에 자동으로 설정하려는 높이와 비교를 하여 더 큰 값의 높이를 리턴해주는 것이다.
class DynamicCell: UITableViewCell {
private let minHeight: CGFloat = UIScreen.main.bounds.height * 0.1
...
override func systemLayoutSizeFitting(
_ targetSize: CGSize,
withHorizontalFittingPriority horizontalFittingPriority: UILayoutPrioriy,
verticalFittingPriority: UILayoutPriority
) -> CGSize {
let size = super.systemLayoutSizeFitting(
targetSize,
withHorizontalFittingPriority: horizontalFittingPriority,
verticalFittingPriority: verticalFittingPriority
)
return CGSize(width: size.width, height: max(size.height, minHeight))
}
...
}
이렇게 코드를 작성하게 되면 셀은 제약조건이 설정되고 크기를 지정하려고 할 때 인터셉터를 하게 되어 셀의 최소 높이를 원하는 크기로 변경할 수 있다.
이 방법 외에도 여러 방법이 존재하였지만 7할은 StoryBoard 내에서 속성을 변경하는 방법이 대부분이 었던 것 같다.
아니면 `tableView(_:heightForRowAt:)` 메서드에서 레이아웃을 강제로 업데이트하여 크기를 계산하고 높이를 지정하거나 이와 비슷한 방식들이 많았던 것 같다.
외에도 UITableViewCell 내의 ContentView의 높이를 변경해주어 최소 크기를 변경하는 방법도 존재했었는데,
이 방법은 SnapKit을 사용하는 상황에서는 높이만 제약조건을 업데이트하게 되니 다른 제약조건들이 유지되지않고 한 방향으로 UI 요소들이 쏠리는 현상이 있어 모두 다시 지정해주어야하는 상황이 발생하기 때문에 이 방법을 선택하게 되었다.
이 방법은 명시적이지 않다는 의견도 있지만 현재 나의 환경에서는 가장 합리적인 선택인 것 같았고 추후 더 좋은 방법을 찾게 된다면 이 부분은 리팩토링을 거칠 예정이다.
'iOS > Swift' 카테고리의 다른 글
[Swift] Type 'ChartDataSet' does not conform to protocol 'RangeReplaceableCollection' 에러 해결 방법 (1) | 2024.09.25 |
---|---|
[Swift] 'didSelectItemAt' 함수가 호출되지 않는 이유 (2) | 2023.12.07 |
[Swift] Custom PageViewController (0) | 2022.03.22 |
[Swift] JSONParser - JSONSerialization (0) | 2022.03.16 |
[Swift] JSONParser - Decodable(2) (0) | 2022.03.15 |