관리 메뉴

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

[iOS - swift] textField(_:shouldChangeCharactersIn:replacementString:) newText 구하는 방법 (+ 문자열 처리, Range, NSRange 개념) 본문

iOS 기본 (swift)

[iOS - swift] textField(_:shouldChangeCharactersIn:replacementString:) newText 구하는 방법 (+ 문자열 처리, Range, NSRange 개념)

jake-kim 2021. 9. 5. 21:29

알아야 하는 기본 개념

  • Range
  • NSRange
  • 문자열 처리 메소드
    • .trimmingCharacters(In: .whitespacesAndNewlines), 
    • .replaceingCharacters(in:with:)

Range

  • half-open의 범위를 나타내고 있는 구조체

  • Range는 lowerBound, upperBound프로퍼티가 존재

  • "1..<5"에서 "1..<5"는 Range<Int>객체

let underFive = 0.0..<5.0

underFive.contains(3.14)
// true
underFive.contains(6.28)
// false
underFive.contains(5.0)
// false
  • for문에서도 사용
fro i in 0..<5 {
}
  • lowerBound, upperBound 프로퍼티
(1..<4).lowerBound // 1
(1..<4).upperBound // 4
  • ~= 연산자: 특정 range에 속하는지 확인하는 연산자
(1..<4) ~= 2 // true
  • overlaps 메소드: range끼리 겹치는 부분이 있는지 확인하는 메소드
(1..<4).overlaps((3..<5)) // true
(1..<4).overlaps((4..<5)) // false

NSRange

  • 연속적인 객체를 담고있는 객체에서 하나의 원소에 대한 설명을 위해 사용되는 구조체
    • 배열에서 배열 중 하나의 값, 문자열에서 문자열 중 하나의 문자를 설명하는데 사용되는데 필요한 structure 

  • NSRange 구조체: Range와 의미가 같지만, Range보다 이전 Foundation에 속해 있던 구조체
    • NSRange의 Range값은 (location..<location+length)

  • NSRange > Range 변환 방법: Range(NSRange객체, in:) 사용
extension ViewController: UITextFieldDelegate {
    func textField(_ textField: UITextField,
                   shouldChangeCharactersIn range: NSRange,
                   replacementString string: String) -> Bool {

        guard let oldString = textField.text, 
        	let newRange = Range(range, in: oldString) else { return true }

        return true
    }
}
  • 프로퍼티 개념
    • location: 배열에서 현재 원소의 index 위치
    • length: 이전 배열과 비교했을 때 현재 배열에서 변경된 원소의 개수 (추가될때 값은 0, 하나가 삭제되면 값은 1)
// NSRange값 확인용도의 코드

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

        label.text = "range = \(range)"

        return true
    }
}

location 증가: 현재 원소의 index위치 표출
length 갱신: 2개를 삭제할땐 2, 한개를 삭제할땐 1
붙여넣기를 한 경우: location 값 증가

textField(_:shouldChangeCharactersIn:replacementString:) 

  • text가 변경할지에 대한 delegate요청 메소드

  • range: 변경되는 문자열에 관련된 NSRange 값
  • string: 대체 문자열
    • 사용자가 하나 입력: 크기가 1인 문자열
    • 사용자가 문자열 붙여넣기 수행: 여러개 문자열
    • 사용자가 하나 이상 문자열 삭제: 빈 문자열

하나씩 입력
붙여넣기
length값 변화: 삭제한 경우

문자열 처리 메소드

  • trimmingCharacters(in:): 문자열의 왼쪽, 오른쪽 끝에있는 character를 삭제하는 인스턴스 메소드

  • trimmingCharacters(in: .whitespaces): 문자열 양쪽 끝 space 제거
  • trimmingCharacters(in: .whitespacesAndNewlines): 양쪽 끝 space와 newLines 제거
let str = "\n1234\nabcd defg\n"
let ex1 = str.trimmingCharacters(in: .whitespaces) // \n1234\nabcd defg\n
let ex2 = str.trimmingCharacters(in: .whitespacesAndNewlines) // 1234\nabcd defg
  • replacingCharacters(in:with:): in에 해당되는 NSRange 범위를 with String으로 변경하는 인스턴스 메소드

textField(_:shouldChangeCharactersIn:replacementString:) 에서 NewText 구하는 방법

  • .replacingCharacters(in:with:) 인스턴스 메소드를 이용하여 string 업데이트 반영 (붙여넣기, 삭제 모두 적용 가능)
    • replacingCharacters의 in에는 Range객체가 필요하므로, NSRange > Range객체로 변경 필요
extension ViewController: UITextFieldDelegate {
    func textField(_ textField: UITextField,
                   shouldChangeCharactersIn range: NSRange,
                   replacementString string: String) -> Bool {

        // Range(range, in: text): 갱신된 range값과 기존 string을 가지고 객체 변환: NSRange > Range
        guard let oldString = textField.text, let newRange = Range(range, in: oldString) else { return true }

        // range값과 inputString을 가지고 replacingCharacters(in:with:)을 이용하여 string 업데이트
        let inputString = string.trimmingCharacters(in: .whitespacesAndNewlines)
        let newString = oldString.replacingCharacters(in: newRange, with: inputString)
            .trimmingCharacters(in: .whitespacesAndNewlines)

        label.text = "newText = \(newString)"

        return true
    }
}

* 참고

- trmmingChracters(in:): 

- Range: https://developer.apple.com/documentation/swift/range

- NSRange: https://developer.apple.com/documentation/foundation/nsrange

- textField(_:shouldChangeCharactersIn:replacementString:): https://developer.apple.com/documentation/uikit/uitextfielddelegate/1619599-textfield

 

Comments