iOS [Swift]/기초λ₯Ό νƒ„νƒ„νžˆ!

[Swift] UITextField ν•œκΈ€ κΈ€μžμˆ˜ μ œν•œ

λˆ„λ¦¬λ‹¬μ΄ν‹€ 2021. 10. 26. 14:31

 

이번 ν¬μŠ€νŒ…μ€ UITextField에 ν•œκΈ€μž…λ ₯μ‹œ κΈ€μžμˆ˜ μ œν•œν•˜λŠ” κΈ°λŠ₯을 μ •λ¦¬ν•˜κΈ° μœ„ν•¨μž…λ‹ˆλ‹€!

μ΄λ²ˆμ— κ°œλ°œν•˜λ©΄μ„œ κΈ€μžμˆ˜ μ œν•œμ΄ μžˆλŠ” λ©”μ„Έμ§€λ₯Ό λ³΄λ‚΄λŠ” κΈ°λŠ₯을 λ„£κ²Œ λλŠ”λ°, μ˜μ–΄λ‚˜ 이λͺ¨μ§€λ‘œλŠ” κΈ€μžμˆ˜ μ œν•œμ΄ 잘 λ™μž‘ν–ˆλŠ”λ°, ν•œκΈ€ μž…λ ₯μ‹œ 버그가 μžˆλ”λΌκ΅¬μš” 😭

 

예λ₯Όλ“€λ©΄ 5자 μ œν•œμ΄λΌκ³  ν• λ•Œ "κ°€λ‚˜λ‹€λΌγ…" μ΄λ ‡κ²Œ "ㅏ"λ₯Ό μΉ˜μ§€ λͺ»ν•˜κ²Œ λ˜κ±°λ‚˜, "κ°€λ‚˜λ‹€λΌλ§˜"을 치고 싢은데 "κ°€λ‚˜λ‹€λΌλ§ˆ"+"ㅁ"이 μž…λ ₯이 μ•ˆλ˜κ±°λ‚˜, "κ°€λ‚˜λ‹€λΌλ§ˆ"μ—μ„œ 계속 νƒ€μ΄ν•‘μ‹œ "마" 뢀뢄에 νƒ€μ΄ν•‘ν•˜λŠ” λ¬Έμžκ°€ 계속 μž…λ ₯λ˜κ±°λ‚˜ γ… γ…  κ·Έλž˜μ„œ κ²ͺμ—ˆλ˜ μ‹œν–‰μ°©μ˜€λ₯Ό μ •λ¦¬ν•˜λ©΄μ„œ ν•΄κ²°ν•œ 방법을 μž‘μ„±ν•΄λ‘λ €κ³  ν•΄μš”!!

 


 

μ•„λ§ˆ 이 글은 비인기 κΈ€μ΄λΌμ„œ γ…Žγ…Ž λˆ„κ΅¬μ—κ²Œ λ…ΈμΆœμ΄ 될지 사싀 잘λͺ¨λ₯΄κ² μ§€λ§Œ.. μ΄κΉŒμ§€ μ˜€μ…¨λ‹€λ©΄ μ•„λž˜μ˜ μ½”λ“œλŠ” 본적 λ§ŽμœΌμ‹€κ±°μ—μš”! 

ꡬ글링해보면 TextFieldDelegateμ—μ„œ μ œκ³΅ν•˜λŠ” shouldChangeCharactersIn λ©”μ†Œλ“œλ₯Ό 톡해 μ œν•œν•˜λŠ” 방법이 κ°€μž₯ 보편적이고 일반적인 λ°©λ²•μ΄λ”λΌκ΅¬μš”~~ shouldChangeCharactersIn λ©”μ†Œλ“œλŠ” delegate둜 μ§€μ •λœ textField에 λ­”κ°€ 타이핑이 되면 λ“€μ–΄μ˜€κ²Œ λ˜λŠ” λ©”μ†Œλ“œμ—μš”~~

μ•„!! ν˜Ήμ‹œ μ•„λž˜μ˜ μ½”λ“œκΉŒμ§€ μ‹œλ„ν•΄λ³΄μ‹  뢄이면 μ €~~κΈ°μ•„λž˜ ν•΄κ²°λ°©λ²•μœΌλ‘œ λ°”λ‘œ skipν•˜μ…”λ„ μ’‹μŠ΅λ‹ˆλ‹€ πŸ‘‰

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        // backspace ν—ˆμš©
        if let char = string.cString(using: String.Encoding.utf8) {
            let isBackSpace = strcmp(char, "\\b")
            if isBackSpace == -92 {
                return true
            }
        }

        guard let text = textField.text else { return false }
        if text.count >= MAX_LENGTH {
            return false
        }

        return true
    }

μ΄λ ‡κ²Œ γ…Žγ…Žγ…Ž 5μžμž…λ ₯을 ν–ˆμ„λ•Œ backspace도 먹톡이 되면 μ•ˆλ˜λ‹ˆκΉŒ, backspaceκ°€ μž…λ ₯으둜 λ“€μ–΄μ™”μ„λ•ŒλŠ” ν˜„μž¬ κΈ€μžμˆ˜μ™€ 상관없이 μž…λ ₯받을 수 μžˆλ„λ‘ μΈμ½”λ”©ν•΄μ„œ μ°ΎλŠ” λ°©μ‹μœΌλ‘œ μ μš©ν•΄μ€¬μ–΄μš”!

 


 

얼핏 보면 잘 λ™μž‘ν•˜λŠ” 것 κ°™μ£ ~~? 그런데 μ—¬κΈ°μ„œ "κ°€λ‚˜λ‹€λΌλ§ˆ" + μžμŒμ„ ν–ˆμ„λ•Œ, 받침이 μž…λ ₯λ˜μ§€ μ•Šμ•„μš”. 이미 MAX_LENGTH둜 μ§€μ •ν•œ 5μžκ°€ λ˜μ—ˆλ‹€κ³  νŒλ‹¨ν•˜κΈ° λ•Œλ¬Έμ΄μ£ ~ κ·Έλž˜μ„œ γ… γ…  shouldChangeCharactersIn λ©”μ†Œλ“œλ₯Ό ν†΅ν•΄μ„œλŠ” μ•ˆλ˜κ² κ΅¬λ‚˜ μ‹Άμ—ˆμ–΄μš”.

PS. μ΄λ ‡κ²Œ ν•œκΈ€μž…λ ₯μ‹œ 받침이 μž…λ ₯λ˜μ§€ μ•ŠλŠ” 버그가 textField λŒ€μ‹  textView둜 μ μš©ν•˜λ©΄ λœλ‹€λŠ” ν¬μŠ€νŒ…μ„ λ΄€λŠ”λ°, μ œκ°€ 직접 ν•΄λ΄€μŠ΅λ‹ˆλ‹€. λ˜‘κ°™μ΄ μ•ˆλ©λ‹ˆλ‹€. μ‹œκ°„λ‚­λΉ„ ν•˜μ§€λ§ˆμ„Έμš”~~

 

λ‹€λ₯Έ 방법을 찾아보닀가.. λ§Œμ•½μ— textField의 κΈ€μžμˆ˜λ₯Ό ν™•μΈν•΄μ„œ μ›ν•˜λŠ” 길이보닀 κΈΈλ©΄ κ·Έλƒ₯ μž˜λΌμ„œ 보여주면 마치 λ”± κ·Έ κΈΈμ΄κΉŒμ§€λ§Œ 보여지지 μ•Šμ„κΉŒ? λΌλŠ” μž‘μ „μœΌλ‘œ λ³€κ²½ν•΄λ΄€μ–΄μš”. shouldChangeCharactersIn 이 λ©”μ†Œλ“œλŠ” 과감히 버리고.. μ˜΅μ €λ²„λ₯Ό μΆ”κ°€ν•΄μ£Όμ—ˆμ–΄μš”.

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

UITextField에 λ­”κ°€ λ³€ν™”κ°€ 생기면 textDidChangeλΌλŠ” λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜λ„λ‘ ν• κ±°κ³ , 이 λ©”μ†Œλ“œλŠ” μ•„λž˜μ™€ κ°™μ•„μš”.

@objc func textDidChange(noti: NSNotification) {
        if let text = messageTextField.text {
            if text.count >= MAX_LENGTH {
                let fixedText = text.subString(startIndex: 0, endIndex: MAX_LENGTH - 1)
                messageTextField.text = fixedText
            }
        }
    }

κ·Έλƒ₯ λ‚΄κ°€ μ§€μ •ν•œ 길이보닀 κΈΈλ©΄ μ§€μ •ν•œ κΈΈμ΄κΉŒμ§€λ§Œ 지라쀘~ ν•˜κ³  말이죠. 그런데...

μ΄λ ‡κ²Œ γ… γ…  5자라고 ν–ˆμ„λ•Œ 5μžκΉŒμ§€λ§Œ λ³΄μ—¬μ§€λŠ”κ±΄ λ§žμ•„μš”..그런데 뭐 μΉ λ•Œλ§ˆλ‹€ 5번째 κΈ€μžκ°€ λ°”λ€Œμ–΄λ²„λ¦¬λŠ” ν˜„μƒμ΄.. 그리고 μ§€μš°λŠ” κ³Όμ •μ—μ„œλ„ νƒ€μ΄ν•‘ν–ˆλ˜ λ¬Έμžλ“€μ΄ κ°‘μžκΈ° 막 λ“±μž₯ν•˜λŠ” 그런 κΈ°κ΄΄ν•œ ν˜„μƒμ΄..또λ₯΄λ₯΄...γ…‹γ…‹γ…‹

μ €λŠ” μ²˜μŒμ—λŠ” λ­”κ°€ bufferκ°™μ€κ²Œ μžˆμ–΄μ„œ, 거기에 기둝된 λ¬Έμžλ“€μ΄ λ‚˜μ˜€λŠ” 거라고 생각을 ν–ˆλŠ”λ°μš”~ 그게 μ•„λ‹ˆλ”λΌκ΅¬μš”.

 

원인은 textField의 μž…λ ₯ ν¬μ§€μ…˜(μ§€κΈˆ μž…λ ₯λ˜μ–΄μ•Ό ν•  자리)κ°€ 6번째 κΈ€μžκ°€ μ•„λ‹ˆλΌ, 5λ²ˆμ§Έμ— 머물러 있기 λ•Œλ¬Έμ΄μ˜€μ–΄μš”.

즉, "μΌμ΄μ‚Όμ‚¬μ˜€" 라고 타이핑을 ν•˜λ©΄ μ œκ°€ μ›ν–ˆλ˜ μž…λ ₯ ν¬μ§€μ…˜μ€ "였" λ‹€μŒμ— μœ„μΉ˜ν•΄μ„œ 타이핑을 해도 "였" μ΄ν›„λ‘œλŠ” κ·Έλƒ₯ 지리기λ₯Ό λ°”λž¬μ–΄μš”. ν•˜μ§€λ§Œ μ‹€μ œλ‘œλŠ”.. "였" μœ„μΉ˜μ— μž…λ ₯ν¬μ§€μ…˜μ΄ μ„€μ •λ˜λŠ” κ±°μ£ . κ·Έλž˜μ„œ "였"λΌλŠ” ν¬μ§€μ…˜μ˜ κΈ€μžκ°€ 계속 λ°”λ€ŒλŠ” ν˜„μƒμ΄.. 😭

 

그럼 μž…λ ₯ ν¬μ§€μ…˜λ§Œ "였" λ’€λ‘œ μ„€μ •ν•΄μ£ΌλŠ” 꼼수(?)만 있으면 μ–΄λ–¨κΉŒ, μ‹Άμ–΄μ„œ μ•„λž˜μ™€ 같이 해결방법을 μ°Ύμ•˜μ–΄μš”!

 

 

 

해결방법

@objc func textDidChange(noti: NSNotification) {
        if let text = messageTextField.text {
            if text.count >= MAX_LENGTH {
                let fixedText = text.subString(startIndex: 0, endIndex: MAX_LENGTH - 1)
                messageTextField.text = fixedText + " "
                
                let when = DispatchTime.now() + 0.01
                DispatchQueue.main.asyncAfter(deadline: when) {
                    self.messageTextField.text = fixedText
                }
            }
        }
    }

μ΄λ ‡κ²Œ μž…λ ₯ν•œ 문자 뒀에 " " 곡백 ν•˜λ‚˜λ₯Ό μΆ”κ°€ν•΄μ£Όλ©΄μ„œ μž…λ ₯ν¬μ§€μ…˜μ„ 마치 "였"λ‹€μŒμœΌλ‘œ μž„μ˜λ‘œ λ§Œλ“€μ–΄ λ²„λ¦¬λŠ”κ±°μ£ .

μ˜λ¬Έμ΄λ‚˜ 이λͺ¨μ§€ 등은 영ν–₯이 μ—†μ§€λ§Œ.. 이게 ν•œκΈ€μ΄ μ΄ˆμ„±, 쀑성, μ’…μ„±μœΌλ‘œ 이루어지기 λ•Œλ¬Έμ— 이런 μ²˜λ¦¬κ°€ ν•„μš”ν•˜λ”λΌκ΅¬μš”.

화면상에 λ™μž‘μ€ 잘 ν•΄κ²°ν•œ 것 같은데.. κ·Έλž˜λ„ μ–Έμ œκΉŒμ§€λ‚˜ 꼼수이기 λ•Œλ¬Έμ— πŸ˜‚

λ‹€λ₯Έ λ°©λ²•μœΌλ‘œ ν•œκΈ€μž…λ ₯μ‹œ κΈ€μžμˆ˜ μ œν•œν•˜λŠ” 것 κ΄€λ ¨ν•΄μ„œ ν•΄κ²°ν•˜μ‹  λΆ„ 있으면 κ³΅μœ ν•΄μ£Όμ‹œλ©΄ 쒋을 것 κ°™μ•„μš”~~

 

그럼 μ˜€λŠ˜λ„ λˆ„κ΅°κ°€μ—κ²Œ 도움이 λ˜μ—ˆκΈΈ λ°”λž˜μš” πŸ™