UITableView Programmatically Practice

Panther·2021년 4월 10일
1
post-custom-banner

스토리보드만을 활용한 TableView 구현은 아래 링크에서 내용을 확인하실 수 있습니다.

https://velog.io/@panther222128/UITableView

스토리보드와 XIB를 활용한 Custom Cell 생성 및 TableView 구현은 아래 링크를 참고하실 수 있습니다.
https://velog.io/@panther222128/UITableView-with-XIB-Practice

먼저 특별한 속성을 갖지 않지만 어떤 내용을 담을 수 있으면서 UITableView로부터 상속받은 객체를 생성했습니다.

class CustomTableView: UITableView {

    // none

}

ViewController는 생성한 UITableView를 갖도록 합니다. 아래 내용을 보면 customTableView의 delegate와 dataSource를 self로 했는데, 프로토콜 채택은 이후에 설명하겠습니다.

class ViewController: UIViewController {
    
    private var customTableView: CustomTableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureTableView()
        tableViewDelegate()
    }
    
    func configureTableView() {
        customTableView = CustomTableView()
        customTableView.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(customTableView)
        customTableView.topAnchor.constraint(equalTo: view.topAnchor, constant: 120).isActive = true
        customTableView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 40).isActive = true
        customTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -40).isActive = true
        customTableView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -40).isActive = true
    }
    
    func tableViewDelegate() {
        customTableView.delegate = self
        customTableView.dataSource = self
    }

}

Custom Cell을 만듭니다. override init부분에 reuseIdentifier를 보면 스토리보드 혹은 XIB에서 했었던 것처럼 재사용을 위한 Identifier를 설정하게 될 것을 암시합니다. setUpCellsetUpLabel은 각각 Cell의 layout과 label 추가 및 label의 글자 색상, 폰트, 정렬을 구현한 부분으로 자신이 원하는 바에 맞게 조절하면 됩니다.

class CustomTableViewCell: UITableViewCell {

    private var memberNameLabel: UILabel!
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setUpCell()
        setUpLabel()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setUpCell()
        setUpLabel()
    }
    
    func setUpCell() {
        memberNameLabel = UILabel()
        contentView.addSubview(memberNameLabel)
        memberNameLabel.translatesAutoresizingMaskIntoConstraints = false
        memberNameLabel.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor).isActive = true
        memberNameLabel.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor).isActive = true
        memberNameLabel.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor).isActive = true
        memberNameLabel.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor).isActive = true
    }
    
    func setUpLabel() {
        memberNameLabel.textColor = .black
        memberNameLabel.font = UIFont.systemFont(ofSize: 32)
        memberNameLabel.textAlignment = .center
    }

}

ViewController로 돌아와서 아래 함수를 추가합니다. forCellReuseIdentifier가 포함되어 있음을 알 수 있습니다.

func registerTableView() {
        customTableView.register(CustomTableViewCell.classForCoder(), forCellReuseIdentifier: "cellIdentifier")
    }

그리고 ViewController 가장 밑에 Table View Delegate 프로토콜을 위한 아래 내용을 추가합니다. 내용을 보면 보여줄 데이터가 몇 개인지, 그리고 보여줄 cell이 무엇인지 작성하고 있습니다. 아직 작성하지 않은 data.memberName이 있는데, 아래 코드 다음 부분에서 예시로 작성한 데이터를 남기겠습니다. func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 메소드는 셀의 높이를 설정합니다. 저는 80으로 줬습니다.

스토리보드를 활용하거나 XIB를 활용할 때처럼 재사용을 위한 Identifier 작성을 정확하게 해야 합니다. 아래 내용에서 let cell = customTableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath) as! CustomTableViewCell에 해당합니다. 앞서 ViewController에서 registerTableView() 메소드에서 forCellReuseIdentifier: "cellIdentifier"를 작성했으니 동일하게 "cellIdentifier"로 설정합니다.

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.memberName.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = customTableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath) as! CustomTableViewCell
        cell.memberNameLabel.text = data.memberName[indexPath.row]
        return cell
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 80
    }
    
}

보여주려고 했던 데이터는 구조체로 간단하게 작성했습니다.

struct Data {
    let memberName = ["효정", "미미", "유아", "승희", "지호", "비니", "아린"]
}

실행 모습은 아래와 같습니다. 이미지 밑에 ViewController 전체 코드를 남기겠습니다.

class ViewController: UIViewController {
    
    private var customTableView: CustomTableView!
    private let data = Data()

    override func viewDidLoad() {
        super.viewDidLoad()
        configureTableView()
        registerTableView()
        tableViewDelegate()
    }
    
    func configureTableView() {
        customTableView = CustomTableView()
        customTableView.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(customTableView)
        customTableView.topAnchor.constraint(equalTo: view.topAnchor, constant: 120).isActive = true
        customTableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 40).isActive = true
        customTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -40).isActive = true
        customTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -40).isActive = true
    }
    
    func registerTableView() {
        customTableView.register(CustomTableViewCell.classForCoder(), forCellReuseIdentifier: "cellIdentifier")
    }
    
    func tableViewDelegate() {
        customTableView.delegate = self
        customTableView.dataSource = self
    }

}

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.memberName.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = customTableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath) as! CustomTableViewCell
        cell.memberNameLabel.text = data.memberName[indexPath.row]
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 80
    }
    
}
post-custom-banner

1개의 댓글

comment-user-thumbnail
2022년 10월 15일

도움 받고 갑니다! 감사합니다!!

답글 달기