UITableView Footer에서 Autolayout 사용하기

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의 높이로 지정해주게 된다. 각 줄이 의미하는 코드는 쉬우므로 생략. 결과를 바로 보자.