인프런 커뮤니티 질문&답변
스위프트, UIKit 에서 테이블 뷰 내 텍스트뷰 높이 조절
작성
·
48
0

지금 당근마켓의 내물건 팔기를 구현하고 있습니다.
전체적으로 UITableView로 만들고 각 셀마다 맞는 셀을 구현했습니다.
텍스트 뷰에 글을 작성하면 텍스트뷰의 높이가 글자 수에 맞춰 늘어나는데, 이때 키보드는 화면 하단에 고정되어 있는것으로 판단됩니다.
그래서 아래와 같이 구현해봤습니다.
class FeedViewController: UIViewController {
// MARK: - Variable
private let tableSection: [String] = ["이미지", "제목", "내용"]
var selectedImages: [UIImage] = []
// MARK: - UI Components
private let feedTableView: UITableView = {
let tableView = UITableView(frame: .zero, style: .insetGrouped)
tableView.separatorStyle = .none
tableView.showsVerticalScrollIndicator = false
tableView.alwaysBounceVertical = false
tableView.isScrollEnabled = true
return tableView
}()
...
// MARK: - Layout
private var feedTableViewBottomConstraint: NSLayoutConstraint!
private var registerButtonTopConstraint: NSLayoutConstraint!
private func configureConstraints() {
view.addSubview(feedTableView)
view.addSubview(registerFeedButton)
feedTableView.translatesAutoresizingMaskIntoConstraints = false
registerFeedButton.translatesAutoresizingMaskIntoConstraints = false
// 제약 조건 저장
feedTableViewBottomConstraint = feedTableView.bottomAnchor.constraint(equalTo: registerFeedButton.topAnchor, constant: -10)
registerButtonTopConstraint = registerFeedButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -10)
NSLayoutConstraint.activate([
// 테이블뷰 제약조건
feedTableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
feedTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
feedTableView.topAnchor.constraint(equalTo: view.topAnchor),
feedTableViewBottomConstraint,
// 버튼 제약조건
registerFeedButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 15),
registerFeedButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -15),
registerFeedButton.heightAnchor.constraint(equalToConstant: 50),
registerButtonTopConstraint
])
// 키보드 노티피케이션 설정
setupKeyboardNotifications()
}
private func setupKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
@objc private func keyboardWillShow(_ notification: Notification) {
if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
// 키보드가 올라오면 테이블뷰의 bottom을 키보드의 top에 맞춤
feedTableViewBottomConstraint.constant = -keyboardFrame.height + 100
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
}
@objc private func keyboardWillHide(_ notification: Notification) {
// 키보드가 내려가면 테이블뷰의 bottom을 버튼의 top으로 복원
feedTableViewBottomConstraint.constant = -10
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
그리고 ContentInputCell 이라고해서 텍스트뷰를 입력하는 곳에는 아래와 같이 작성했습니다.
// MARK: - UI Component
private let contentTextView: UITextView = {
let textView = UITextView()
textView.text = "오늘 하루는 어땠나요? 😀"
textView.backgroundColor = .systemBackground
textView.layer.cornerRadius = 5
textView.layer.masksToBounds = true
// 글자 수에 따라 크기가 늘어가게 하기 위함
textView.isScrollEnabled = false
textView.textAlignment = .left
textView.textContainerInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
textView.textColor = .secondaryLabel
textView.backgroundColor = .systemBackground
textView.font = UIFont.systemFont(ofSize: 16, weight: .bold)
return textView
}()
...
private func configureConstraints() {
contentView.addSubview(contentTextView)
contentTextView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
contentTextView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
contentTextView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
contentTextView.topAnchor.constraint(equalTo: contentView.topAnchor),
contentTextView.bottomAnchor.constraint(equalTo: contentView.keyboardLayoutGuide.topAnchor, constant: 5),
contentTextView.heightAnchor.constraint(greaterThanOrEqualToConstant: 350)
])
}
// MARK: - Extension: UITextViewDelegate
extension ContentInputCell: UITextViewDelegate {
func textViewDidChange(_ textView: UITextView) {
guard let tableView = tableView else { return }
let contentSize = textView.sizeThatFits(CGSize(width: textView.bounds.width, height: .infinity))
if textView.bounds.height != contentSize.height {
tableView.contentOffset.y += contentSize.height - textView.bounds.height
UIView.setAnimationsEnabled(false)
tableView.beginUpdates()
tableView.endUpdates()
UIView.setAnimationsEnabled(true)
}
}
}
extension ContentInputCell {
var tableView: UITableView? {
var view = superview
while view != nil && !(view is UITableView) {
view = view?.superview
}
return view as? UITableView
}
}답변 1
0
안녕하세요, 인프런 AI 인턴입니다. 듀듀님.
스위프트와 UIKit에서 텍스트뷰의 높이를 동적으로 조절하는 방법에 대해 고민하고 계신 것 같아요. 문제를 해결하기 위해 몇 가지 사항을 확인해보시는 것을 추천드립니다.
UITextView의 높이 업데이트:
textViewDidChange메서드 내에서contentSize.height를 사용해 텍스트뷰의 높이를 측정하고 셀의 높이를 업데이트하도록 구현하고 계시네요. 이 방법은 옳습니다. 그러나textViewDidChange메소드 안에서tableView.contentOffset.y를 조정하는 부분은 높이 변화에 따른 스크롤 위치 조정을 위함이라면, 불필요할 수 있습니다. UITableView의beginUpdates()/endUpdates()호출만으로도 셀의 높이 변화에 따라 테이블뷰가 자연스럽게 조정될 수 있습니다.
Auto Layout Constraints:
- Constraints에서
contentTextView.bottomAnchor.constraint(equalTo: contentView.keyboardLayoutGuide.topAnchor, constant: 5)를 사용하는데,keyboardLayoutGuide는 보통 키보드와의 위치를 조정할 때 사용되며 여기서는 필요하지 않을 수 있습니다. 대신contentTextView의 높이를UITextViewDelegate메서드에서 동적으로 업데이트하도록 조정해보세요.
- Constraints에서
키보드와의 상호작용:
- 키보드가 나타남에 따라 뷰가 잘못된 위치나 크기로 나타날 수 있는데,
keyboardWillShow와keyboardWillHide메서드에서 테이블뷰의bottomConstraint를 올바르게 조정하고 계신 것 같습니다.
- 키보드가 나타남에 따라 뷰가 잘못된 위치나 크기로 나타날 수 있는데,
이미 많은 부분을 잘 구현하셨으니, 위의 내용을 바탕으로 문제를 한 번 더 검토해보시기 바랍니다. 추가적으로 수정 또는 개선해야 할 부분이 있을 경우 말씀해 주세요.
도움이 되었기를 바랍니다! 😊





