관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] replacingCharacters 문자열 처리 (#UITextField의 shouldChangeCharactersIn 에서 입력된 전체 문자열 구하는 방법) 본문

iOS 응용 (swift)

[iOS - swift] replacingCharacters 문자열 처리 (#UITextField의 shouldChangeCharactersIn 에서 입력된 전체 문자열 구하는 방법)

jake-kim 2023. 11. 6. 01:18

shouldChangeCharactersIn에서 입력된 문자열 구하기

  • shouldChangeCharactersIn 메서드 호출 시점은 사용자가 키보드 입력했을때 호출되며 해당 문자를 허용할 것인지, 비허용할 것인지 true or false를 리턴하는 메서드
  • 현재 타이핑한 문자는 string이고, 변경이 일어난 구간은 range값으로 표현
extension ViewController: UITextFieldDelegate {
    func textField(
        _ textField: UITextField,
        shouldChangeCharactersIn range: NSRange,
        replacementString string: String
    ) -> Bool {
        return true
    }
}
  • 이전에 입력되었던 문자열과 현재 입력한 문자열을 합해서 총 문자열 개수를 알고 싶은 경우?
    • replacingCharacters(in:with:)를 사용하여 구현
    • 이 방법은 많이 알고 있는 방법이지만 replacingCharacters의 동작 원리를 이해하는것이 이 글의 목적
extension ViewController: UITextFieldDelegate {
    func textField(
        _ textField: UITextField,
        shouldChangeCharactersIn range: NSRange,
        replacementString string: String
    ) -> Bool {
        guard let text = textField.text else { return true }
        let lastText = text as NSString
        let allText = lastText.replacingCharacters(in: range, with: text)
        return true
    }
}

replacingCharactes(in:with:)

  • in 인자에 range값을 넣고 with에 변경될 String을 입력
  • range값은 location과 length로 구분되며 location은 시작위치, length는 길이를 의미

ex) "iOS 앱 개발 알아가기" -> "SwiftUI 앱 개발 알아가기" 문자열 변경 방법

  • range를 만들고 replacingCharacters로 변경
    • range 주의할 점: length값은 인덱스가 아닌 문자열의 길이이므로 문자 3개를 교체하라는 의미
let originalString = "iOS 앱 개발 알아가기"
let range = NSRange(location: 0, length: 3)
let nsString = originalString as NSString
let newString = nsString.replacingCharacters(in: range, with: "SwiftUI")
print(newString) // SwiftUI 앱 개발 알아가기
  • 여기서 그냥 String이 아닌 NSString으로 형변환하는 이유는 replacingCharacters 메서드는 NSString 메서드이기 때문

UITextField에 replacingCharacters 적용하여 전체 문자열 구하기

  • UITextField에서 range값이 내려오는데, 핵심은 range.length값 파악하는 것
extension ViewController: UITextFieldDelegate {
    func textField(
        _ textField: UITextField,
        shouldChangeCharactersIn range: NSRange,
        replacementString string: String
    ) -> Bool {
        return true
    }
}
  • range.length: 기존에 입력된 문자열 기준으로 변경점을 의미
  • 만약 기존 문자열에서 문자가 하나 추가되면 기존 문자열을 건들지 않았으므로 length값은 0
  • 기존 문자열에서 두 개를 삭제하면 length값은 2

ex) replacingCharacters로 문자열 추가, 삭제하는 패턴

  • 문자열을 추가하고 싶은 경우 - length값에 0 넣어주기
let originalString = "iOS 앱 개발 알아가기"
let range = NSRange(location: 0, length: 0)
let nsString = originalString as NSString
let newString = nsString.replacingCharacters(in: range, with: "SwiftUI")
print(newString) // SwiftUIiOS 앱 개발 알아가기
  • 문자열을 삭제하고 싶은 경우 - length값에 1넣고 with에 ""값으로 입력
let originalString = "iOS 앱 개발 알아가기"
let range = NSRange(location: 0, length: 1)
let nsString = originalString as NSString
let newString = nsString.replacingCharacters(in: range, with: "")
print(newString) // OS 앱 개발 알아가기
  • 이 원리를 이해한다면 shouldChangeCharactersIn에서 range와 string을 아래처럼 이용하면 이전까지 입력된 값에 현재 입력된 값을 포함하는 처리를 간결하게 표현 가능
extension ViewController: UITextFieldDelegate {
    func textField(
        _ textField: UITextField,
        shouldChangeCharactersIn range: NSRange,
        replacementString string: String
    ) -> Bool {
        guard let text = textField.text else { return true }
        let lastText = text as NSString
        let allText = lastText.replacingCharacters(in: range, with: text)
        
        print("range: \(range), string: \(string), allText: \(allText)")
        
        return true
    }
}

* 전체 코드: https://github.com/JK0369/ExReplacingCharacters

 

Comments