프로그래밍/iOS,macOS
UITextView 사이즈 조정 및 글자 제한, placeholder
chance
2021. 6. 30. 14:01
제한된 숫자만 입력을 제공하는 경우 UITextViewDelegate 의 아래 메쏘드 구현.
최대수보다 1 크게 체크하는데.. 한글과 같이 마지막에 조합이 이루어지는 경우와 특정 글자가 넘어갈 경우만 알림을 보여주기 위함.
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
guard let currentText = textView.text else {
return true
}
let newLength = currentText.count + text.count - range.length
if newLength > maxCharacterCount {
// rx 등을 이용해 제한이 넘었음을 알림
// ex) limitEvent.accept(true)
}
return newLength <= maxCharacterCount + 1
}
1글자가 더 입력 되므로 텍스트 변경 이벤트 수정
func textViewDidChange(_ textView: UITextView) {
guard let currentText = textView.text else { return }
// 별도 placeholder 텍스트가 존재하는 경우 처리
if currentText == placeHolderString { return }
if currentText.count > maxCharacterCount {
// 알림
// ex) limitEvent.accept(true)
let index = currentText.index(currentText.startIndex, offset: currentText.count - 1)
textView.text = String(currentText[currentText.startIndex..<index])
} else {
// 사이즈 조정이 필요한 경우
resizingTextView()
}
}
사이즈 조정
func resizingTextView() {
let size = CGSize(width: textView.frame.width, height: .infinity)
let estimatedSize = textView.sizeThatFits(size)
let flag = estimatedSize.height >= MaxHeightLimit
guard flag != textView.isScrollEnabled else { return }
textView.isScrollEnabled = flag
textView.reloadInputViews()
textView.setNeedsUpdateConstraints()
}
placeholder
func setPlaceHolder() {
if textView.text.isEmpty {
textView.text = placeHolderString
textView.textColor = .gray
} else {
textView.text = ""
textView.textColor = .black
}
}
func textViewDidBeginEditing(_ textView: UITextView) {
setPlaceHolder()
resizeTextView()
// editEvent.accept(true)
}
func textViewDidEndEditing(_ textView: UITextView) {
setPlaceHolder()
// editEvent.accept(false)
}
참고)
붙여넣기 등을 허용할 경우 글자 제한까지만 변경을 허용해야 하는 경우 대략 아래처럼 할 수 있지 않을까?
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
guard var currentText = textView.text else {
return true
}
let newLength = currentText.count + text.count - range.length
if newLength > maxCharacterCount {
// rx 등을 이용해 제한이 넘었음을 알림
// ex) limitEvent.accept(true)
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
let orgRange = Range(range, in: currentText)
currentText.replaceSubrange(orgRange!, with: text)
let endIndex = currentText.index(currentText.startIndex, offsetBy: self.maxCharacterCount)
let result = currentText[currentText.startIndex..<endIndex]
self.textView.text = String(result)
}
}
return newLength <= maxCharacterCount + 1
}