ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • UITableView Header 추가
    iOS/UIKit 2022. 7. 7. 22:34

    view controller 생성 및 UITableView 추가

    background만 설정한 기존의 view controller를 없애고 새로운 view controller를 만들자. 그 다음 UITableView를 사용해야 하기 때문에 다음과 같이 작성하자. 이 상태에서 root view controller로 설정한 뒤 실행하면 3개 cell이 있는 것을 확인할 수 있다.

    import UIKit
    
    class AccountSummaryViewController: UIViewController {
    
        let games = [
            "Pacman",
            "Space Invaders",
            "Space Patrol",
        ]
    
        var tableView = UITableView()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            setup()
        }
    }
    
    extension AccountSummaryViewController {
        private func setup() {
            setupTableView()
        }
    
        private func setupTableView() {
            // delegate, dataSource 설정
            tableView.delegate = self
            tableView.dataSource = self
    
            tableView.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(tableView)
    
            // root view의 safe area 전체를 차지하도록 설정
            NSLayoutConstraint.activate([
                tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
                tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
                tableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
                tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
            ])
        }
    }
    
    extension AccountSummaryViewController: UITableViewDataSource {
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = UITableViewCell()
            cell.textLabel?.text = games[indexPath.row]
            return cell
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return games.count
        }
    }
    
    extension AccountSummaryViewController: UITableViewDelegate {
        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    
        }
    }

     

    table view header 추가

    우선 header로 넣을 AccountSummaryHeader라는 view를 추가하자.

    class AccountSummaryHeaderView: UIView {
    
    }

     

    그 다음 같은 이름의 .xib 파일도 추가한 다음, attribute inspector에서 size를 freeform으로 설정하자. 그래야 사이즈를 맘대로 조절할 수 있다.

     

    그 다음 사이즈를 설정하자.

     

    이 xib 파일에서의 view 구성을 코드에서 사용하기 위해서는 File's owner를 설정해야 한다. 왼쪽에서 File's Owner를 선택한 다음, 오른쪽에서 클래스를 설정하자. 이 상태에서 Assistant를 체크하면 해당 클래스가 연결된 것을 확인할 수 있다.

     

    그 다음 xib 파일의 view를 IBOutlet으로 추가하자.

     

    이후 다음과 같이 코드를 작성하자.

    class AccountSummaryHeaderView: UIView {
        @IBOutlet var contentView: UIView!
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            commonInit()
        }
    
        override var intrinsicContentSize: CGSize {
            // view 자신의 기본 사이즈 설정
            return CGSize(width: UIView.noIntrinsicMetric, height: 144)
        }
    
        private func commonInit() {
            // xib를 프로그램적으로 load하는 코드
            let bundle = Bundle(for: AccountSummaryHeaderView.self)
            bundle.loadNibNamed("AccountSummaryHeaderView", owner: self, options: nil)
            addSubview(contentView)
            contentView.backgroundColor = appColor // 배경색 설정
    
            contentView.translatesAutoresizingMaskIntoConstraints = false
    
            // outlet으로 추가한 view가 클래스의 view에 딱 맞도록 설정
            contentView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
            contentView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
            contentView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
            contentView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        }
    }

     

    그 다음 이 view를 table view의 header로 추가해야 한다. AccountSummaryViewController를 다음과 같이 수정하자.

    extension AccountSummaryViewController {
        private func setup() {
            setupTableView()
            setupTableHeaderView() // 추가
        }
    
        // ...
    
        private func setupTableHeaderView() {
            let header = AccountSummaryHeaderView(frame: .zero)
    
            // 가능한 한 작은 사이즈로 잡히도록 함
            // 이 코드 실행하면 instrinsic size로 설정했던 height가 설정됨
            var size = header.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
            // height는 기본적으로 설정되어 있으므로 width를 설정
            // width는 기기에 따라 달라지기 때문에 이 방식으로 부여
            size.width = UIScreen.main.bounds.width
            header.frame.size = size // size 할당
    
            tableView.tableHeaderView = header // header로 설정
        }
    }

     

    이 상태에서 실행하면 다음과 같이 header가 추가된 것을 확인할 수 있다.

     

    그 다음 .xib 파일에서 constraint를 통해 layout을 잡자. label들은 기본적으로 instrinsic size가 있기 때문에 position만 잡으면 되지만, image는 사이즈도 잡아야 한다.

     

    물론 stack view를 사용하여 constriaint 수를 줄일 수도 있다.

     

    이 상태에서 실행하면 제대로 레이아웃이 잡힌 것을 확인할 수 있다.

     

    물론 이렇게 레이아웃을 완성해도 실행하면 콘솔에서 constraint들 사이의 ambiguity가 있다는 메시지가 뜰 것이다. 이러한 경우 bottom과 trailing 쪽 constraint들의 priority를 999로 낮추면 해결된다. priority가 1000이면 반드시 적용되고, 1000보다 작으면 optional하게 적용된다. 전자를 solid, 후자를 soft라고 부른다.

     

    Content Hugging Compression Resistance(CHCR)

    보면 vertical stack과 image를 감싸는 horizontal stack의 spacing을 100이 넘는 값에서 4로 줄여버리면, vertical stack이 늘어나는 것을 관찰할 수 있다. 왜일까?

    우선 vertical stack의 size inspector를 보면 다음과 같다.

     

    image view의 size inspector는 다음과 같다.

     

    image view가 content hugging priority가 더 높고, 따라서 horizontal stack의 spacing이 감소할 때, image는 width를 유지하고, vertical stack은 width가 늘어나는 것이다. 이러한 우선순위를 xcode에서 자동으로 부여하기 때문에, 우리는 우리가 예상한 방식대로 레이아웃을 잡을 수 있는 것이다.

     

    Reference

    https://www.udemy.com/course/the-swift-arcade-professional-ios-development-course-uikit/

    'iOS > UIKit' 카테고리의 다른 글

    로그아웃 기능 구현 및 세부 수정  (0) 2022.07.12
    Table view cell 구성  (0) 2022.07.08
    Scroll Views 개요  (0) 2022.07.07
    Tab view 구성하기  (0) 2022.07.06
    Container View Controllers  (0) 2022.07.06

    댓글

Designed by Tistory.