본문 바로가기

프로그래밍/iOS,macOS

UITextView 사이즈 조정 및 글자 제한, placeholder

제한된 숫자만 입력을 제공하는 경우 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
}