UITableView에서의 FooterView

  • UITableView에서 FooterView를 사용할땐 frame 기반의 코드를 작성해야만 한다.
  • 아마도 버그이지 않을까 싶지만, 언제나 그랬듯 개발자가 직접 수정해야만 한다.
  • 먼저 어떻게 버그가 발생하는지 알아보자.

  • 우선 다음과 같이 커스텀 뷰를 만들고 오류가 나지 않도록 적절한 autolayout을 적용했다.
  • 이제 이 커스텀 뷰를 UITableViewFooterView로 지정해보자.
class ViewController: UIViewController {
    @IBOutlet private var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.tableFooterView = FooterView()
    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        3
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell()
        cell.textLabel?.text = "\(indexPath)"
        return cell
    }
}
  • 간단한 코드라 코드에 대한 내용은 생략하고 바로 결과를 보자.

  • 자, 보다시피 완전히 망가져버렸다…
  • 반면에 frame 기반으로 작성해보면 어떻게 될까
tableView.tableFooterView = FooterView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 250))

  • 자 이처럼 frame에 기반한 코드로 처리하면 잘 나오게 된다.
  • 그러나 만약 높이가 동적으로 변해야만 하는 뷰라면 어떻게 해야할까?

동적으로 변하는 뷰에서 높이를 설정하는 방법

  • 우선 이 방법도 frame에 기반한 코드이긴 하지만 높이를 수동으로 지정해주는 방법은 아니다.
override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        guard let footerView = tableView.tableFooterView else { return }
        let width = tableView.frame.width
        let size = footerView.systemLayoutSizeFitting(CGSize(width: width, height: UIView.layoutFittingCompressedSize.height))
        guard footerView.frame.height != size.height else { return }
        footerView.frame.size.height = size.height
}
  • 위와 같은 코드를 추가하게 되면 FooterView에 높이를 계산할 수 있고, 이를 다시 FooterView의 높이로 지정해주게 된다.
  • 각 줄이 의미하는 코드는 쉬우므로 생략.
  • 결과를 바로 보자.