• 카테고리

    질문 & 답변
  • 세부 분야

    모바일 앱 개발

  • 해결 여부

    미해결

UITableViewCell 높이 관련 질문입니다.

23.03.08 19:43 작성 23.03.08 19:43 수정 조회수 798

1

- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요!
- 먼저 유사한 질문이 있었는지 검색해보세요.
- 서로 예의를 지키며 존중하는 문화를 만들어가요.
- 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.

활용 8번 앱을 만들어 보고 있습니다. 활용 8에 MyTableViewCell에 memberNameLabel과 addressLabel이 UIStackView에 추가 되어 있고, 제가 임의로 UIStackView 다른 Label도 넣어보았습니다. 그런데 글자가 짤리더라구요. 아무래도 tableView.rowHeight가 설정되어 있어서 그런 것 같은데, tableView.rowHeight를 고정으로 설정하지 않고 높이를 동적으로 설정하는 방법이 있을까요?

검색해서 아래 두 코드도 추가해봤는데 높이가 고정으로 잡히네요 ㅠㅠ 해결 방법이 없을까요? 답변 부탁드립니다. 감사합니다.

 tableView.rowHeight = UITableView.automaticDimension
 tableView.estimatedRowHeight = UITableView.automaticDimension
extension ViewController: UITableViewDelegate {
   
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }
    
}

답변 2

·

답변을 작성해보세요.

0

감사합니다! 해결되었습니다 :)

네네 화이팅 하세요 :)

0

해당 관련된 내용이 10번 프로젝트에서 나오긴 합니다.
(해당 프로젝트 관련해서 참고해 보시는 것이 더 정확합니다.)

(1) 레이블 자체의 높이의 오토레이아웃을 예를 들어 50으로 설정하는 것이 아니라, 50 >= 이런식으로 설정해주어야 하고 (늘어날 수 있어야 하니 최소 50이상..이런방식으로)

(2) 또한 높이에 우선순위를 주어서 더 늘어날 수 있는 개념인 Resistance Priority도 설정해주셔야 하고 (레이블끼리 우선 순위를 설정해야.. 특정 레이블의 높이가 짤리지 않게 높이가 버티고 있을 수 있게)

(3) 레이블의 line수도 0으로 설정해주셔야 합니다. (0줄은 글자의 길이가 늘어나서 라인수가 늘어나면.. 높이를 늘리겠다는 뜻입니다. 1, 2줄 이렇게 고정이 아닌 것이죠.)


(4) 그 이후에 아래 높이를 추정할 수 있도록 델리게이트 설정을 해주셔야 겠죠. 물론 tableView.delegate = self도 잊으시면 안 되고요.

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
      return UITableView.automaticDimension
}


위의 내용들 잘 고려해서 설정하시면 무리없이 설정할 수 있으시리라 봅니다. :)

감사합니다...!

안녕하세요! 답변 감사합니다.
하지만, 10강의 경우 storyboard기반이여서 10강을 참고해서 codebase로 작성하는데 어려움이 있습니다. 다만 말씀해주신것을 토대로 코드를 수정해서 테스트 해봤는데, 높이가 고정으로 표시되더라구요. 최하단의 코드 한 번 봐주시면 감사하겠습니다.(예제의 UIImageViwe는 임의로 삭제하였습니다.)

말씀해주신 대로 label의 높이 값을 특정 값 이상(greaterThanOrEqualToConstant)으로 설정 하였고, numberOfLines을 모두 0으로 설정하였습니다. 그리고 estimatedHeightForRowAt delegate도 추가하였으나 아래 이미지 처럼 높이가 고정됩니다.

image

 

import UIKit

final class ViewController: UIViewController {
    
    private let tableView = UITableView()
    
    var memberListManager = MemberListManager()
    
    lazy var plusButton: UIBarButtonItem = {
        let button = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(plusButtonTapped))
        return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .white
        setupDatas()
        setupTableView()
        setupNaviBar()
        setupTableViewConstraints()
    }
    
    
    func setupNaviBar(){
        title = "회원 목록"
        
        let appearance = UINavigationBarAppearance()
        appearance.configureWithOpaqueBackground()
        appearance.backgroundColor = .white
        navigationController?.navigationBar.tintColor = .systemBlue
        navigationController?.navigationBar.standardAppearance = appearance
        navigationController?.navigationBar.compactAppearance = appearance
        navigationController?.navigationBar.scrollEdgeAppearance = appearance
        
        self.navigationItem.rightBarButtonItem = self.plusButton
    }
    
    func setupTableView(){
        tableView.dataSource = self
        tableView.delegate = self
//        tableView.rowHeight = UITableView.automaticDimension
//        tableView.estimatedRowHeight = UITableView.automaticDimension
        tableView.register(MyTableViewCell.self, forCellReuseIdentifier: "MemberCell")
    }
    
    func setupTableViewConstraints(){
        view.addSubview(tableView)
        tableView.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0),
            tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 0),
            tableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 0),
            tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0)
        ])
    }
    
    func setupDatas(){
        memberListManager.makeMembersListData()
    }
    
    @objc func plusButtonTapped() {
        let detailVC = DetailViewController()
        navigationController?.pushViewController(detailVC, animated: true)
    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return memberListManager.getMemberList().count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "MemberCell", for: indexPath) as! MyTableViewCell
        
        cell.member = memberListManager[indexPath.row]
        cell.selectionStyle = .none
        
        return cell
    }
}

extension ViewController: UITableViewDelegate {

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }
    
}

extension ViewController: MemberDelegate {
    func addNewMember(_ member: Member) {
        memberListManager.makeNewMember(member)
        tableView.reloadData()
    }
    
    func update(index: Int, _ member: Member) {
        memberListManager.updateMemberInfo(index: index, member)
    }
}
import UIKit

class MyTableViewCell: UITableViewCell {
    var member: Member? {
        didSet {
            guard let member = member else { return }
            memberNameLabel.text = member.name
            addressLabel.text = member.address
        }
    }
    let memberNameLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.boldSystemFont(ofSize: 12)
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    let addressLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 10)
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    let testLabel2: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 12)
        label.text = "테스트1"
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    let testLabel3: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 12)
        label.text = "테스트2"
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    let stackView: UIStackView = {
        let sv = UIStackView()
        sv.axis = .vertical
        sv.distribution = .fill
        sv.alignment = .fill
        sv.spacing = 5
        sv.translatesAutoresizingMaskIntoConstraints = false
        return sv
    }()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: .default, reuseIdentifier: reuseIdentifier)
        setupStackView()
    }
    
    
    // 필수 생성자 :: 상위에 지정생성자, 필수생정자가 있을 때 지정생성자를 재정의 하려면 반드시 필수생성자를 정의해야한다.
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setupStackView(){
        stackView.addArrangedSubview(memberNameLabel)
        stackView.addArrangedSubview(addressLabel)
        stackView.addArrangedSubview(testLabel2)
        stackView.addArrangedSubview(testLabel3)
        
//        self.addSubview(mainImageView)
        self.addSubview(stackView)
        
    }
    
    // 스토리 보드 생성자
    override func awakeFromNib() {
        super.awakeFromNib()
    }
    
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
    
    override func updateConstraints() {
        setConstrains()
        super.updateConstraints()
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
    }
    
    func setConstrains(){

        NSLayoutConstraint.activate([
            memberNameLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 50),
            addressLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 50),
            testLabel2.heightAnchor.constraint(greaterThanOrEqualToConstant: 50),
            testLabel3.heightAnchor.constraint(greaterThanOrEqualToConstant: 50),
        ])

        NSLayoutConstraint.activate([
            stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
            stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
            stackView.topAnchor.constraint(equalTo: self.topAnchor),
            stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
        ])
    }
}

 

일단 어떤 식으로 구현하길 원하시는지, 저도 전체적인 그림을 먼저 봐야 알 것 같아서..
프로젝트를 압축해서 보내주세요.
we.love.code.allen@gmail.com

(기존 제 강의의 내용을 바꿔서 구현하고 계시기 때문에 제가 모든 내용을 유추하기는 어렵습니다... 코드만 보고 판단하기도 어렵고요..)

setConstrains( ) 호출 코드를

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: .default, reuseIdentifier: reuseIdentifier)
        setupStackView()
        setConstrains() 
}


생성자에 넣고, updateContraints( ) 에서 지워보시겠어요?

override func updateConstraints() {
        // setConstrains()      // <===========삭제
        super.updateConstraints()
}