ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [UITextField] 일정 포멧에 맞춰서 / 마스크 입혀주기
    iOS/UIKit 2022. 1. 22. 22:16

    뭐라고 설명하기 어려운것 같아서 영상으로 설명을 대신한다.

    아래 예시는 전화번호 포멧에 맞춰서 표시형식을 맞춰준 것이다.

    간단하게 설명하자면, 텍스트필드 입력값을 받아서 포멧에 맞게 수정한 뒤에 다시 텍스트필드값을 바꿔주는 로직이다.

    구현은 아래와 같다.

    extension String {
        var decimalFilteredString: String {
            return String(unicodeScalars.filter(CharacterSet.decimalDigits.contains))
        }
        func formated(by patternString: String) -> String {
            let digit: Character = "#"
    
            let pattern: [Character] = Array(patternString)
            let input: [Character] = Array(self.decimalFilteredString)
            var formatted: [Character] = []
    
            var patternIndex = 0
            var inputIndex = 0
    
            // 2
            while inputIndex < input.count {
                let inputCharacter = input[inputIndex]
    
                // 2-1
                guard patternIndex < pattern.count else { break }
    
                switch pattern[patternIndex] == digit {
                case true:
                    // 2-2
                    formatted.append(inputCharacter)
                    inputIndex += 1
                case false:
                    // 2-3
                    formatted.append(pattern[patternIndex])
                }
    
                patternIndex += 1
            }
    
            // 3
            return String(formatted)
        }
    }

    코드에 대해서 설명하자면 아래와 같다.

    1. String값을 필터링해서 decimalDigits값을 리턴한다.
    2. 예를들어서 "1a2b3c-456_def"가 있다면 "123456"만을 리턴한다.
    3. 필터링한 input string을 순회한다.
      1. 지정한 패턴을 모두 소모하면 더이상 패턴매칭을 하지 않는다.
      2. 패턴에 자리가 숫자가 들어갈 자리라면, input string에서 현재 인덱스를 결과값에 넣어준다.
        input값을 하나 소모했으니 인덱스도 하나 키워준다.
      3. 그게 아니라면 패턴에 들어간 문자를 그대로 결과값에 넣어준다.]
    4. 패턴매칭을 완료한 결과를 리턴한다.

    이렇게 만든 함수를 textField의 text와 연결하면 된다.

    -기호 포함 12자리일때 까지는 중간번호가 3자리인 ###-###-####
    -기호 포함 13자리일 때에는 중간번호가 4자리인 ###-####-####의 포멧으로 적용된다.

    textField.rx.text
        .orEmpty
        .distinctUntilChanged()
        .map { text in
            switch text.count {
            case 13:
                return text.formated(by: "###-####-####")
            default:
                return text.formated(by: "###-###-####")
            }
        }
        .bind(to: textField.rx.text)
        .disposed(by: disposeBag)

    댓글

Designed by Tistory.