XLOG

[UIKit] UITextField 한글 글자 수 제한 본문

Swift/UIKit

[UIKit] UITextField 한글 글자 수 제한

X_PROFIT 2023. 1. 30. 14:42

우리는 UITextField를 컨트롤 하기 위해 UITextFieldDelegate를 상속받아야 한다.

 

UITextFieldDelegate에는

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {}

함수가 존재하는데 return 값이 true 면 수정이 가능하며, false 면 textfield 값의 수정이 불가능 하다.

 

맨처음 접근은 위의 함수에서 string 값의 갯수를 카운트하여 갯수에 따라 return 값을 조절해 주려고 했다.

하지만 한글은 초성, 중성, 종성이 결합되어 한글자로 카운트가 되어야 한다. 하지만 위에 함수에서는 종성이 받침으로 들어가는 것이 아닌 그 다음 글자의 초성으로 인식을 하여 10글자로 제한을 하면 10번째 글자는 받침이 적용되지 않는 문제가 있었다.

 

그렇다면 언제 한글처리가 되는걸까?

func textFieldDidChangeSelection(_ textField: UITextField) {}

위 함수에서 변화가 완료가 되면 호출 되는 함수 이다. 즉 맨 처음 언급한 함수에 인자에 shouldChange가 들어가는 것을 봐서, 맨 처음 언급한 함수 뒤에 호출이 되는 함수이다. 여기서에선 textField 의 text 값이 제대로 하나의 글자로 합성되서 호출이 된다.

 

그래서 내가 생각한 방법은 원하는 textField 함수가 호출이 되는 시점에  판단을 하는 것이 아닌 textFieldDidChangeSelection에서 판단을 하고 그 다음 글자에 제한을 주는 방법이었다.

 

그러기 위해 판단을 위한 변수가 추가로 필요했다.

전체 코드를 공유하면

import UIKit

class TestTextFieldViewController: UIViewController {
    
    var realText: String = ""
    var isEnable: Bool = true
    
    private let textField: UITextField = {
        let textField = UITextField()
        textField.borderStyle = .line
        textField.translatesAutoresizingMaskIntoConstraints = false
        return textField
    } ()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        setTextField()
    }
    private func setTextField() {
        textField.delegate = self
        view.addSubview(textField)
        NSLayoutConstraint.activate([
            textField.heightAnchor.constraint(equalToConstant: 20),
            textField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            textField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
            textField.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        ])
    }
}

extension TestTextFieldViewController: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if !isEnable {
            if let char = string.cString(using: String.Encoding.utf8) {
                let isBackSpace = strcmp(char, "\\b")
                if isBackSpace == -92 {
                    isEnable = true
                    return true
                } else {
                    return false
                }
            }
        }
        return true
    }
    
    func textFieldDidChangeSelection(_ textField: UITextField) {
        if textField.text!.count > 10  || !isEnable {
            isEnable = false
            self.textField.text = realText
        } else {
            isEnable = true
            realText = textField.text!
        }
    }
    
}

isEnable이란 변수로 textFieldDidChangeSelection에서 판단을 한 후 그 다음 키값에 대해 textField 함수가 판단하는 기준을 준다.

여기서 BackSpace의 경우의 값은 입력이 되어야 하게 때문에 isEnable 이 false인 경우에 추가 기준을 주어 한글 글자수를 제한하면 된다.