optional func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool
이 method는 두번째 파라미터 range를 통해 추가되거나 삭제할 범위를 전달하고,
세번째 파라미터 string으로 현재 입력받은 문자열을 전달합니다.
그리고 return값이 true여야 실제로 textField에 입력할 수 있습니다.
만약 이 method 안에서 텍스트필드에 입력된 최종 텍스트를 가져오려면,
아직 true 값을 return을 하기 전 이기 때문에,
위의 파라미터들과 NSString을 조합해야 텍스트필드에 입력된 최종 텍스트를 가져올 수 있습니다.
extension ViewController: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let input = NSString(string: textField.text ?? "")
let output = input.replacingCharacters(in: range, with: string)
print("printed:", input, output)
return true
}
}
// printed: 1
// printed: 1 12
// printed: 12 123
// printed: 123 1234
위에서 언급한 것처럼, input(textField.text)에 저장된 값은 아직 return 하기 전이기 때문에 출력되지 않습니다.
그래서 replacingCharacters(in: range, with: string)으로 현재 추가되거나 삭제할 범위를 골라서 현재 추가한 String으로 바꿔줍니다.
참고로 텍스트를 지울 경우 string엔 빈 문자열 ""이 전달됩니다.
반대로 최종 문자열을 구현할 때 String이 제공하는 method를 사용한다면, NSRange를 Range로 바꿔줘야하기 때문에 구현이 복잡해 질 수 있습니다. 그래서 testField.text를 NSString 타입으로 변경하는 방법을 사용하는게 편합니다.
extension ViewController: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let input = textField.text ?? ""
if let myRange = Range(range, in: input) {
if let output = textField.text?.replacingCharacters(in: myRange, with: string) {
print("printed:", input, output)
}
}
return true
}
}
// printed: 1
// printed: 1 12
// printed: 12 123
// printed: 123 1234
여러 사람들이 '불편하다' 라고 해서 불편합니다. 라고 얼렁뚱땅 넘어가려고 했지만, 확인을 해봤습니다.
NSRange를 Range 타입으로 바꾸고 method를 사용하는 부분에서는 큰 차이는 없지만, optional 타입으로 인스턴스들이 생성됩니다.
옵셔널 바인딩을 통해 사용해주어야 하기 때문에 String을 NSString으로 바꿔서 사용하는게 더 간결합니다.
RxSwift로 바꾸면 훨씬 간결합니다. 😅