[iOS/Swift] 테이블뷰/컬렉션뷰 스크롤 없이 모든 내용 표시하는 방법

2025. 4. 3. 10:16iOS/UIKit

728x90
반응형

🧸 시작

항상 UITableView나 UICollectionView를 사용할 때는 보통 고정된 높이를 지정하고 스크롤을 통해서 콘텐츠를 보여주는 방식으로 많이 사용해왔다.

그런데 테이블뷰나 컬렉션뷰의 셀 개수가 몇 개인지 미리 알 수 없기 때문에, 높이를 특정 값으로 지정하는 게 쉽지 않다.
특히, 스크롤을 사용하지 않고 모든 셀이 한눈에 보이도록 동적으로 높이를 조절해야 하는 경우에는 별도의 처리가 필요하다.

이 글에서는 테이블뷰나 컬렉션뷰의 높이를 자동으로 조절하는 방법을 알아보겠다.

 

 

🧸 intrinsicContentSize를 활용한 높이 조절

UIKit에서는 intrinsicContentSize라는 개념을 제공하는데, 이걸 이용하면 테이블뷰나 컬렉션뷰의 높이를 내부 콘텐츠 크기에 맞게 자동으로 조절할 수 있다.
일반적으로 UIView는 고유한 크기가 없지만, 특정 뷰들은 intrinsicContentSize를 재정의해서 자체적인 크기를 가질 수 있도록 한다.

아래와 같이 intrinsicContentSize를 오버라이드하면, 테이블뷰나 컬렉션뷰가 자신의 콘텐츠 크기(contentSize)에 맞춰 자동으로 늘어나도록 만들 수 있다.

override public var intrinsicContentSize: CGSize {
    return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
}
  • width는 기본값을 유지 (UIView.noIntrinsicMetric)
  • height는 현재 contentSize.height 값으로 설정

이렇게 하면 테이블뷰나 컬렉션뷰의 내용이 바뀔 때마다 높이가 자동으로 조절된다.

 

🧸 데이터 변경 시 높이 갱신

그런데 reloadData()를 호출한다고 해서 자동으로 intrinsicContentSize가 갱신되지는 않는다.

그래서 데이터를 다시 불러올 때마다 invalidateIntrinsicContentSize()를 호출해서 뷰가 크기를 다시 계산하도록 강제해야 한다.

override public func reloadData() {
    super.reloadData()
    DispatchQueue.main.async { [weak self] in
        self?.invalidateIntrinsicContentSize()
    }
}

여기서 DispatchQueue.main.async를 사용하는 이유는, reloadData()가 즉시 실행된다고 해도 contentSize가 완전히 업데이트되기 전에 크기를 계산하면 잘못된 값이 나올 수 있기 때문이다.
그래서 메인 스레드에서 비동기적으로 실행해서 안전하게 처리한다.

 

✔️  실제 적용 예시

1. 테이블뷰를 동적으로 크기 조절하는 뷰

class DynamicTableView: UITableView {
    override var intrinsicContentSize: CGSize {
        return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
    }

    override func reloadData() {
        super.reloadData()
        DispatchQueue.main.async { [weak self] in
            self?.invalidateIntrinsicContentSize()
        }
    }
}

2. Auto Layout을 사용할 때

let tableView = DynamicTableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
parentView.addSubview(tableView)

NSLayoutConstraint.activate([
    tableView.leadingAnchor.constraint(equalTo: parentView.leadingAnchor),
    tableView.trailingAnchor.constraint(equalTo: parentView.trailingAnchor),
    tableView.topAnchor.constraint(equalTo: parentView.topAnchor)
])
 
 
👉 heightAnchor는 따로 지정하지 않아도 intrinsicContentSize를 통해 자동으로 설정된다.

 

 

▶️ 언제 이런 방법이 필요할까 ?

✔️ 스크롤 없이 모든 셀을 보여줘야 할 때

✔️ UITableView/UICollectionView를 UIScrollView 내부에 넣을 때

✔️ 동적으로 크기가 변하는 리스트를 만들어야 할 때

스크롤을 사용하는 일반적인 경우라면 높이를 지정하는 게 맞지만,
위와 같은 상황에서는 intrinsicContentSize를 활용하면 자동으로 높이가 조절되는 동적 리스트를 만들 수 있다.

이제 테이블뷰나 컬렉션뷰의 높이를 직접 계산하는 번거로운 작업 없이, 더 깔끔하게 구현할 수 있을 것이다!

 

 

 

 

728x90
반응형

 

 

 

 

 

728x90
반응형