[ios] 친절한 어플리케이션(1) - TextField에서 콤마(,)로 숫자 단위 구분하기
안녕하세요. 현재 제가 진행하고 있는 가상화폐 관련 프로젝트에는 사용자가 구매했던 당시 코인의 가격과 총 얼마치를 구매했는지를 입력하는 TextField들이 있습니다. 물론 TextField를 올리고 사용자가 입력한 데이터를 처리하는 것은 어렵지 않습니다.
하지만 저의 프로젝트에서는 금액을 입력을 해야하기 때문에 조금만 단위가 커져도 ,
를 통한 구분이 없기 때문에 액수를 정확히 입력했는지를 확인하기도 어렵고 보기에도 그렇게 좋지는 않습니다.
200000
: 단위 구분이 없는 값
200,000
: 단위 구분을 한 값
오늘은 이렇게 사소해보이지만 사용자에게는 보다 편리함을 제공하는, 즉 친절한 프로그램을 만드는데 필요한 방법 중 하나인 TextField에 값을 입력할 때 자동으로 ,를 넣어주어 자릿수를 구분해주는 법을 알아보도록 하겠습니다.
UITextFieldDelegate
먼저 어느정도 스위프트와 iOS 공부를 하신 분들이라면 이러한 작업은 왠지 관련 프로토콜과 Delegate를 사용해야 할 것 같은데? 라는 생각을 하셨을 것입니다.
맞습니다! 저 또한 그렇게 생각을 했습니다. 하지만 정확히 어떤 행위를 해야할지 몰랐기 때문에 가장 먼저 구글링을 통한 공부였고 여러 소스들을 참고하여 제가 이해할 수 있는 수준으로 직접 이것저것 만져보면서 확인해가며 코드를 작성해보았습니다.
먼저 UITextFieldDelegate
를 준수함으로써 우리는 다음의 메소드를 사용할 수 있습니다.
주의깊게 살펴보아야 할 인자는 두 개입니다.
textField
: 우리가 사용하게 될 UITextField
를 참조하는 변수입니다.
replacementString
: 방금 입력한 문자열 값입니다.
이 메소드를 return true
만 구현하고 string
과 textField.text
를 출력하는 코드를 작성 후 프로젝트를 실해하고 값을 입력해보세요. (물론 textField.delegate = self
를 해주셔야 합니다.) 생각한 결과가 출력이 되나요?
아닐겁니다. string
은 방금 사용자가 입력한 문자열 값이 되고 textField.text
의 값은 string
이 합쳐지기 전의 문자열입니다. 일반적인 입력에서 string
은 사용자가 입력한 문자 하나 하나로 길이가 1인 문자열이 넘어와 입력한 만큼 메소드가 호출되지만 특정 문자열을 복사하고 해당 TextField
에 붙여넣기를 하면 string
값은 붙여 넣어진 문자열 전체 값이 됩니다.
그리고 이러한 string
과 이전의 문자열을 이용하여 입력된 문자를 해당 문자와 합쳐 입력된 값을 반영할 것인지 아니면 따로 추가적인 작업을 할 것인지, 혹은 반영하지 않을 것인지를 Bool
값을 반환함으로써 이를 알립니다. 즉 false
가 반환되면 입력된 값을 이전 문자열에 합치지 않는다는 것이고 (추가적인 작업) , true
가 반환되면 입력된 값을 정상적으로 이전의 문자열과 합쳐 반영한다는 것입니다.
저는 이 메소드를 활용해 원하는 기능을 구현할 것입니다.
NumberFormatter
그 다음으로 살펴보아야 할 것은 Formatter
입니다. 이 Formatter
에서도 저는 NumberFormatter
를 사용하여 기존의 값을 원하는 값의 형식(Format)으로 바꿔줄 것입니다. 제가 사용할 포맷은 다음과 같습니다.
먼저 ,를 통해 숫자를 구분해줄 것이기 때문에 numberStyle
은 .decimal
로 설정합니다.
지역에 따라 .decimal
도 차이가 있으니 디바에스에 설정된 지역으로 값을 설정합니다.
허용할 수 있는 최대 소숫점자리를 설정합니다. 저는 소숫점을 허용하지 않을 것이므로 0으로 설정합니다.
보다 자세한 사항은 다음의 링크를 참조하세요 . Using Number Formatters
Implementation
이제 본격적으로 위의 내용들을 바탕으로 코드를 작성해보도록 하겠습니다.
TextField의 키보드 타입을 NumberPad로 바꿔줍니다.
- 그리고 그 밑에 위와 같은 코드를 작성합니다. 하나씩 살펴보도록 하겠습니다.
처음 입력하는 것이라면 textField
에 값이 존재하지 않겠지만 그것이 아니라면 이미 위의 코드를 통해 ,
를 통해 구분된 값들이 존재할 것입니다. 그 값들과 새로 들어온 값 검사한 후 합치기 위해 ,
를 제거합니다. 여기서 formatter.groupingSeparator
는 .decimal
의 구분점을 의미하고 이를 ""
으로 대체한다는 것으로 ,
를 제거한다는 의미입니다,
이렇게 ,
가 제거된 문자열과 새로 입력된 문자열을 일단 합칩니다.
하지만 새로 입력된 값이 숫자가 아닌 값이 들어오면 6번으로 넘어가고 숫자의 형태가 맞다면 블록안으로 들어갑니다.
formatter.number(from:)
의 인자로 들어간 값이 숫자만으로 이루어진 문자열이면 해당 문자를 숫자로 바꾼 값을 NSNumber
의 형태로 반환하지만 그렇지 않으면 nil
을 반환합니다.
입력된 값이 숫자로 이루어진 문자열이 맞다면 위에서 합친 문자열인 beforeFormattedString
을 원하는 포맷으로 설정해 놓은 formatter
로 NSNumber
의 형태로 바꾼 후 그 값을 다시 String
의 형태로 바꿔줍니다.
그렇게 최종적으로 변환된(,
값이 들어간) 값을 textField
에 할당합니다. 그리고 이렇게 임의로 값을 바꿔주었기 때문에 false
를 반환합니다.
3번에서 설명한 것과 마찬가지로 새로 입력된 값이 숫자로 이루어진 문자열이 아닌 경우에는 두 가지가 있습니다. 바로 지우는 행위인 백스페이스를 눌렀거나 말 그대로 숫자로 이루어진 문자열이 아닌 경우입니다.
백스페이스가 입력되면 들어오는 string
의 값은 빈 문자열입니다. 즉 백스페이스가 입력되면 맨 마지막의 문자열을 자르고 잘린 문자열의 ,
를 앞으로 하나씩 당겨주어야 하기 때문에 다시 포맷 과정을 거쳐 textField
에 할당합니다.
만일 숫자가 아닌 다른 입력 값이 들어온다면 입력된 값은 추가되지 않습니다.
마무리
오늘은 이렇게 사소하지만 사용자에게 편리함을 줄 수 있는 기능을 공부해보았습니다. 어쩌면 개발자에게는 귀찮은 작업이 될 수 있으나 그것을 조금만 감수하면 사용자들은 보다 편리하고 직관적으로 어플리케이션을 사용할 수 있으니 항상 이렇게 섬세한 부분까지 신경쓰는 개발을 하도록 노력해야겠습니다. 감사합니다.
Source : github
참고자료
- Using Number Formatter
- [How do you dynamically format a number to have commas in a UITextField entry?