[iOS] TextField 글자수 제한하기 (한글)

sso0022·2020년 12월 21일
0

iOS

목록 보기
8/12
post-thumbnail

개린이가 쓴 글이므로 오류가 있을 수 있음을 미리 알려드립니다 🐹 (꾸벅)

오늘은 글자수 제한을 두는 textField 만들어보기 ~

닉네임의 글자수를 2글자 - 8글자로 제한하도록 해볼게요 :)
이것도 여러가지 방법이 있겠지만 ,,, 아래 예제는 UITextFieldDelegate와 NotificationCenter를 이용하였습니다.

📒 UITextFieldDelegate

class ViewController: UIViewController, UITextFieldDelegate {
    @IBOutlet weak var textField: UITextField!

    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        textField.delegate = self
      
	}
}

textField의 글자수 등을 바로바로 확인할 수 있도록 UITextFieldDelegate 프로토콜을 채택해주고
사용할 textField의 위임자를 자기자신(해당VC)로 설정해줍시다!



public protocol UITextFieldDelegate : NSObjectProtocol {

    
    @available(iOS 2.0, *)
    optional func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool // return NO to disallow editing.

    @available(iOS 2.0, *)
    optional func textFieldDidBeginEditing(_ textField: UITextField) // became first responder

    @available(iOS 2.0, *)
    optional func textFieldShouldEndEditing(_ textField: UITextField) -> Bool // return YES to allow editing to stop and to resign first responder status. NO to disallow the editing session to end

    @available(iOS 2.0, *)
    optional func textFieldDidEndEditing(_ textField: UITextField) // may be called if forced even if shouldEndEditing returns NO (e.g. view removed from window) or endEditing:YES called

    @available(iOS 10.0, *)
    optional func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) // if implemented, called in place of textFieldDidEndEditing:

    
    @available(iOS 2.0, *)
    optional func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool // return NO to not change text

    
    @available(iOS 13.0, *)
    optional func textFieldDidChangeSelection(_ textField: UITextField)

    
    @available(iOS 2.0, *)
    optional func textFieldShouldClear(_ textField: UITextField) -> Bool // called when clear button pressed. return NO to ignore (no notifications)

    @available(iOS 2.0, *)
    optional func textFieldShouldReturn(_ textField: UITextField) -> Bool // called when 'return' key pressed. return NO to ignore.
}

-> UITextFieldDelegate에 들어있는 메소드들

   @available(iOS 2.0, *)
    optional func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool // return NO to not change text

위처럼 여러가지의 메소드들이 있지만 오늘 사용해볼 것은 위에 적혀있는 메소드입니다 :)


func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        guard let text = textField.text else {return false}
        
        // 최대 글자수 이상을 입력한 이후에는 중간에 다른 글자를 추가할 수 없게끔 작동
        if text.count >= maxLength && range.length == 0 && range.location < maxLength {
            return false
        }
        
        return true
    }

위의 코드를 적용해주면 개발자가 max로 설정해둔 길이를 넘어선 후에
중간으로 바를 이동해서 새로운 것을 추가 입력하려고 해도 입력되지 않습니다.


적용 전 | 적용 후
:-------------------------:|:-------------------------:
|


위의 메소드에 대해 자세히 설명되어 있는 글이 있어서 첨부합니다.
더 자세히 알고싶으시다면 아래 링크를 확인해주세요 :) 저도 이해가 잘 안되었는데 여기서 많은 도움을 받았습니다
자세한 설명



✨ NotificationCenter


NotificationCenter.default.addObserver(self,
                                               selector: #selector(textDidChange(_:)),
                                               name: UITextField.textDidChangeNotification,
                                               object: textField)

그리고 viewDidLoad 부분에 옵저버를 추가해줍니다 :)
text가 변경이 완료되면 textDidChange 함수가 실행됩니다.


@objc private func textDidChange(_ notification: Notification) {
        if let textField = notification.object as? UITextField {
            if let text = textField.text {
                
                if text.count > maxLength {
                    // 8글자 넘어가면 자동으로 키보드 내려감
                    textField.resignFirstResponder()
                }
                
                // 초과되는 텍스트 제거
                if text.count >= maxLength {
                    let index = text.index(text.startIndex, offsetBy: maxLength)
                    let newString = text[text.startIndex..<index]
                    textField.text = String(newString)
                }
                
                else if text.count < 2 {
                    warningLabel.text = "2글자 이상 8글자 이하로 입력해주세요"
                    warningLabel.textColor = .red
                    
                }
                else {
                    warningLabel.text = "사용 가능한 닉네임입니다."
                    warningLabel.textColor = .green

                }
            }
        }
    }

  1. 우선 글자수가 정해놓은 max수치보다 커지면 키보드가 자동으로 내려가도록 하여
    사용자가 더이상 입력을 하지 않도록 유도하였습니다.
    '>='가 아닌 '>'로 한 이유는 한글의 특성상 자음만 친다고 글자가 완성된 것이 아닌데
    count는 자음만 쳐도 수가 올라가기 때문에 안녕하세ㅇ -> 키보드 내려감을 방지하기 위해
    이렇게 설정하였습니다.

텍스트가 최대 값을 넘어갈 경우에는
text를 앞에서 최대 값까지 잘라내어 다시 저장해주는 방식을 사용하여
maxLength를 넘어가지 않도록 해주었습니다.

  1. 최소 값보다 작을 때는 경고 문구를 보여주도록 하였습니다.
  2. 원하는 범위에 들어왔을 때는 사용 가능하다는 문구를 보여주도록 하였습니다.


🎬 활용하기



저는 2글자 - 8글자 사이에 들어오도록 구현하였습니다.
8글자가 넘어가는 순간 키보드가 내려가는 것을 확인하실 수 있어요!
저는 오른쪽 위의 완료버튼의 활성화 여부도 넣어주었어요
그래서 닉네임이 원하는 범위에 있지 않으면 완료버튼도 누를 수 없게 세팅해주었습니다 !



아무래도 영어와 다르게 한글은 한 글자의 구분이 애매해서
구현하는 게 어려운 부분이 있는 것 같아요 ㅠ_ㅠ
코드가 완벽하지 않을 수 있습니다 ... 혹시 오류가 있다면 댓글 남겨주세요 !!



[참고자료]

링크
링크

profile
Studying iOS 🐹

0개의 댓글